1 相关介绍
事务可以理解为一个或一组sql语句组成的执行单元,MySQL数据库中innodb和bdb引擎支持事务。事务有以下四个特性:
-
A (Atomicity):原子性,即一个事务不能再拆分,事务的操作要么都执行,要么都不执行
-
C (Consistency):一致性,即数据库从一个一致性状态变换到另一个一致性状态
-
I (Isolation):隔离性,即一个事务的执行不受其他事务的干扰,并发执行的事务之间不能相互干扰
-
D (Durability):持久性,即一个事务一旦提交,对数据库的改变是永久性的
2 事务分类
2.1 隐式事务
事务没有明显的开始和结束标记,比如insert、update、delete语句。
2.2 显式事务
事物具有明显的开始和结束标记,要先关闭自动提交功能
set autocommit = 0;
步骤一般如下所示
1、开启事务
set autocommit = 0;
start transaction; # 这句写不写均可
2、编写事务中的sql语句,比如select、insert、update、delete语句
3、结束事务
commit;
# 或者 rollback;
3 隔离级别
3.1 并发问题
当多个事务访问数据库的相同数据时,如果没有采取隔离机制,就会引发各种并发问题:
- 脏读:有两个事务A和B,A读取了被B更新但还没有提交的数据,随后B回滚,那么A读到的数据就是临时无效的
- 不可重复读:有两个事务A和B,A读取了某个字段,然后B修改了该字段并提交,A再次读取时发现值不同了
- 幻读:有两个事务A和B,A读取了某个数据,然后B往该表插入了一些新的行,A再次读就会发现多了几行
不可重复读和幻读的区别是不可重复读重点在于update和delete,而幻读的重点在于insert。
3.2 隔离级别
隔离级别 | 描述 |
---|---|
READ UNCOMMITTED | 允许事务读取其他事务未提交的数据,脏读、不可重复读、幻读都会出现 |
READ COMMITTED | 只允许事务读取被其他事务提交的修改,能解决脏读,不能解决不可重复读和幻读(Oracle默认) |
REPEATABLE READ | 一旦事务开始,能确保事务可以多次从一个字段中读取相同的值。在事务的进行期间,感受不到其他事务对该字段的更新。可以解决脏读和不可重复读(MySQL默认) |
SERIALIZABLE | 在事务进行期间,禁止其他事务对该表执行插入、更新和删除操作,能解决所有并发问题 |
3.3 演示并发问题
以下操作均在命令提示符中进行
现数据库有account表,并有以下数据。
使用两个命令提示符来模拟两个事务(事务A是黑色背景,事务B是蓝色背景),以最低隔离级别为例来演示,其他隔离级别的演示类似。
1、把两个事务的隔离级别都设置为最低的READ UNCOMMITTED
set session transaction isolation level read uncommitted;
2、MySQL 8+查看隔离级别的指令如下
select @@transaction_isolation;
3、事务A修改数据,并未提交
4、事务B可以查看到A未提交的数据
5、事务A回滚,B发生了脏读和不可重复读