包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。一个支持事务(Transaction)的数据库,必需要具有这四种特性,否则在事务过程(Transaction processing)当中无法保证数据的正确性,交易过程极可能达不到交易方的要求。 ⑴ 原子性(Atomicity) 第一个原子性,这个是最简单的。说的是一个事务内所有操作共同组成一个原子包,要么全部成功,要么全部失败回滚。失败回滚的操作事务,将不能对事务有任何影响。 ⑵ 一致性(Consistency) 原子性只保证了一个事务内的所有操作同一性,大家同生死,不会出现你死了,我还活着。但是,原子性并没有保证大家同一时刻一起生,一起死。计算机指令是有先后顺序的,这样就决定了一个事务的提交,会经历一个时间过程,那么如果事务提交进行到了一半,我读取了数据库,会不会读到中间结果? 为了防止这样的情况,数据库事务的一致性就规定了事务提交前后,永远只可能存在事务提交前的状态和事务提交后的状态,从一个一致性的状态到另一个一致性状态,而不可能出现中间的过程态。也就是说事务的执行结果是量子化状态,而不是线性状态。 ⑶ 隔离性(Isolation) 事务的隔离性,基于原子性和一致性,因为事务是原子化,量子化的,所以,事务可以有多个原子包的形式并发执行,但是,每个事务之间互不干扰。由于多个事务可能操作同一个资源,不同的事务为了保证隔离性,会有很多锁方案,当然这是数据库的实现。 ⑷ 持久性(Durability) 持久性,当一个事务提交之后,数据库状态永远的发生了改变,这个事务只要提交了,哪怕提交后宕机,他也确确实实的提交了,不会出现因为刚刚宕机了而让提交不生效,是要事务提交,他就像洗不掉的纹身,永远的固化了,除非你毁了硬盘。
1.更新丢失:和别的事务读到相同的东西,各自写,自己的写被覆盖了。(谁写的快谁的更新就丢失了) 第一类更新丢失(回滚丢失,Lost update):A事务撤销时,把已经提交的B事务的更新数据覆盖了。这是完全没有事务隔离级别造成的,通常数据库的实现是不允许发生这种情况。 第二类更新丢失(覆盖丢失,Second lost update):A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失。 2.脏读:读到别的事务未提交的数据。(万一回滚,数据就是脏的无效的了) 3.不可重复读:两次读之间有别的事务修改。 4.幻读:两次读之间有别的事务增删。
1.第一类更新丢失:A事务撤销时,把已经提交的B事务的更新数据覆盖了 事务1:开启事务 ---------------->事务2:开启事务 事务1:查询账户余额为1000元 ---------------->事务2:查询账户余额为1000元 ---------------->事务2:汇入100元把余额改为1100元 ---------------->事务2:提交事务 事务1:取出100元把余额改为900元 事务1:撤销事务 事务1:余额恢复为1000 元 (丢失更新)
2.第二类更新丢失:A事务覆盖B事务已经提交的数据,造成B事务所做操作丢失。 事务1:开启事务 ------------>事务2:开启事务 事务1:查询账户余额为1000元 ------------>事务2:查询账户余额为1000元 ------------>事务2:取出100元把余额改为900元 ------------>事务2:提交事务 事务1:汇入100元 事务1:提交事务 事务1:把余额改为1100 元 (丢失更新)
3.脏读:一个事务读取到了另外一个事务没有提交的数据(读取未提交数据) 事务1:更新一条数据 ------------->事务2:读取事务1更新的记录 事务1:调用commit进行提交 事务1:开始事务 ------------->事务2:开始事务 ------------->事务2:查询账户余额为2000元 ------------->事务2:取款1000元,余额被更改为1000元 事务1:查询账户余额为1000元(产生脏读) ------------->事务2:取款操作发生未知错误,事务回滚,余额变更为2000元 事务1:转入2000元,余额被更改为3000元(脏读的1000+2000)
事务1:提交事务 按照正确逻辑,此时账户余额应该为4000元
4.不可重复读:在同一事务中,两次读取同一数据,得到内容不同(即不能读到相同的数据内容,前后多次读取,数据内容不一致) 事务1:查询一条记录 -------------->事务2:更新事务1查询的记录 -------------->事务2:调用commit进行提交 事务1:再次查询上次的记录 ***此时事务1对同一数据查询了两次,可得到的内容不同,称为不可重复读
5.幻读:同一事务中,用同样的操作读取两次,得到的记录数不相同(前后多次读取,数据总量不一致) 事务1:查询表中所有记录 -------------->事务2:插入一条记录 -------------->事务2:调用commit进行提交 事务1:再次查询表中所有记录 ***此时事务1两次查询到的记录是不一样的,称为幻读
5.1.第二类更新丢失的问题,如果数据库用户使用方式不对,是有可能出现问题的。 通常有两种方式可以解决这个问题:
#悲观锁 #悲观锁就是锁定要更新的这一行,然后在事务提交之前不让其他事务对该行数据做任何操作 #直至释放行锁 select money from account where id=10 for update money = money + 100 update account set money = money where id =10 #乐观锁 #乐观锁是在并发的表上加一个version字段,更新的时候只有版本号大于当前版本号才能更新成功 select money,version from account where id=10 for update money = money + 100 version = version + 1 update account set money = money where id =10 and version > version5.2.幻读 如何避免:实行序列化隔离模式,在任何一个低级别的隔离中都可能会发生。
5.3.不可重复读 有两个策略可以防止这个问题的发生:
推迟事务2的执行,直至事务1提交或者回退。这种策略在使用锁时应用。而在多版本并行控制中,事务2可以被先提交。而事务1,继续执行在旧版本的数据上。当事务1终于尝试提交时,数据库会检验它的结果是否和事务1、事务2顺序执行时一样。如果是,则事务1提交成功。如果不是,事务1会被回退。5.4.脏读
脏读发生在一个事务A读取了被另一个事务B修改,但是还未提交的数据。假如B回退,则事务A读取的是无效的数据。这跟不可重复读类似,但是第二个事务不需要执行提交。
不可重复读和幻读到底有什么区别呢? (1)不可重复读是读取了其他事务更改的数据,针对insert与update操作 解决:使用行级锁,锁定该行,事务A多次读取操作完成后才释放该锁,这个时候才允许其他事务更改刚才的数据。 (2)幻读是读取了其他事务新增的数据,针对insert与delete操作 解决:使用表级锁,锁定整张表,事务A多次读取数据总量之后才释放该锁,这个时候才允许其他事务新增数据。
MySQL mysql数据库支持上面四种隔离级别,默认的事务处理级别是’REPEATABLE-READ’,也就是可重复读(因为MySQL采用了gap lock,所以实际上MySQL的RR隔离级别也解决了幻读的问题); 1.查看当前会话隔离级别 select @@tx_isolation; 2.查看系统当前隔离级别 select @@global.tx_isolation; 3.设置当前会话隔离级别 set session transaction isolatin level repeatable read; 4.设置系统当前隔离级别 set global transaction isolation level repeatable read;
Oracle oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别,默认系统事务隔离级别是READ COMMITTED,也就是读已提交; 1.查看系统默认事务隔离级别,也是当前会话隔离级别 –首先创建一个事务 declare trans_id Varchar2(100); begin trans_id := dbms_transaction.local_transaction_id( TRUE ); end; –查看事务隔离级别 SELECT s.sid, s.serial#, CASE BITAND(t.flag, POWER(2, 28)) WHEN 0 THEN ‘READ COMMITTED’ ELSE ‘SERIALIZABLE’ END AS isolation_level FROM v t r a n s a c t i o n t J O I N v transaction t JOIN v transactiontJOINvsession s ON t.addr = s.taddr AND s.sid = sys_context(‘USERENV’, ‘SID’);
参考: https://blog.csdn.net/qq_33591903/article/details/81672260 https://blog.csdn.net/chenyiminnanjing/article/details/82714341 https://blog.csdn.net/chenyang1010/article/details/84425790 https://blog.csdn.net/gaoshan_820822/article/details/4582561