基本概念
· 和事务相关的语句只有DML语句(insert delete update)
· 事务是逻辑上的一组操作,要么都执行,要么都不执行
· 最经典的转账案例:小明给小红转账1000元。其中就涉及两个关键操作:小明余额减少1000元,小红余额增加1000元,事务就是要保证二者同时成功或失败
事务的四大特性 (ACID)
- 原子性(Atomicity): 事务是最小的执行单位,不允许分割
- 一致性(Consistency): 事务必须保证多条DML语句同时成功或同时失败
- 隔离性(Isolation): 各个事务的执行互不干扰,并发执行的事务不会互相影响
- 持久性(Durability): 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
事务的隔离级别
- 第一级别:
读未提交(Read Uncommitted)
- 最低的隔离级别,允许读取尚未提交的数据变更
- 可能会导致脏读、幻读或不可重复读
- 第二级别:
读已提交(Read Committed)
(Oracle默认的隔离级别)- 允许读取并发事务已经提交的数据
- 可以阻止脏读, 但是幻读或不可重复读仍有可能发生
- 第三级别:
可重复读(Repeateable Read)
(MySQL默认的隔离级别)- 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改
- 可以阻止脏读和不可重复读,但幻读仍有可能发生
- 第四级别:
序列化读/串行化读(Serializable)
- 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰。
- 可以防止脏读、不可重复读以及幻读。
- 问题:效率低,事务需要排队执行
并发事务带来的问题
-
脏读(Dirty Read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是 “脏数据” ,依据 “脏数据” 所做的操作可能是不正确的
-
不可重复读(Unrepeatable Read): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不相同。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
-
幻读(Phantom Read): 幻读与不可重复读类似。它发生在一个事务(T1) 读取了几行数据,接着另一个并发事务(T2) 插入了一些数据时。在随后的查询中,第一个事务(T1) 就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
-
注意:
不可重复读和幻读的区别:
· 不可重复读的重点是修改比如多次读取一条记录发现其中某些列的值被修改
· 幻读的重点在于新增或者删除比如多次读取一条记录发现记录增多或减少了。
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读已提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化读 | × | × | × |
事务控制
- MySQL支持事务自动提交
- 使用begin 或 start transaction关闭自动提交机制,开启事务
- rollback 回滚
- commit 提交事务
- 设置、查看事务的全局隔离级别
- 例:
set global transaction isolation level Serializable;
设置隔离级别为串行化读 select @@global.transaction_isolation;
查看隔离级别
- 例: