【MySQL】事务

157 阅读3分钟

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表,并有以下数据。

018-01.png

使用两个命令提示符来模拟两个事务(事务A是黑色背景,事务B是蓝色背景),以最低隔离级别为例来演示,其他隔离级别的演示类似。

1、把两个事务的隔离级别都设置为最低的READ UNCOMMITTED

set session transaction isolation level read uncommitted;

2、MySQL 8+查看隔离级别的指令如下

select @@transaction_isolation;

3、事务A修改数据,并未提交

018-02.png

4、事务B可以查看到A未提交的数据

018-03.png

5、事务A回滚,B发生了脏读和不可重复读

018-04.png

018-05.png

4 相关链接