MySQL 事务图解
作者:熊本极客
链接:https://www.jianshu.com/p/963b8d293937
1.事务是什么?
事务是逻辑上的一组操作,要么都执行,要么都不执行。
例子:假如张三要给李四转账200元,这个转账会涉及到两个关键操作就是:将张三的余额减少200元,将李四的余额增加200元。如果两个操作之间突然出现错误,例如银行系统崩溃导致张三余额减少,而李四的余额没有增加,这样的系统是有问题的。事务就是保证这两个关键操作要么都成功,要么都要失败。
事务的特性
① 原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
② 一致性:执行事务前后,数据保持一致,例如转账业务中,无论事务是否成功,转账者和收款人的总额应该是不变的;
③ 隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
④ 持久性:一个事务被提交之后,对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
2.事务隔离级别及实践
并发事务带来的问题
① 脏读:当事务 T1 正在访问字段 A 并且对进行了修改,而这种修改还没有提交到数据库中。这时另外一个事务 T2 也访问和使用字段 A,但由于事务 T1 修改字段 A 后还没有提交COMMIT
,而那么事务 T2 读到的字段 A 是“脏数据”。
② 丢失修改:事务 T1 读取 A=20,事务 T2 也读取 A=20,事务 T1 修改 A=A-1,事务 T2 也修改 A=A-1,最终结果 A=19,事务 T1 的修改被丢失。
③ 不可重复读:一个事务内多次读同一数据且不一致。例如,事务 T1 在读取两次数据之间,事务 T2 修改了数据,导致事务 T1 两次读取的数据可能不太一样。
④ 幻读:幻读与不可重复读类似。事务 T1 读取了几行数据,接着另一个并发事务 T2 插入了一些数据时。接着事务 T1 就会发现多了一些原本不存在的记录,就好像发生了幻觉一样。
事务隔离级别与并发问题的关系:
隔离级别 | 脏读 | 不可重复读 | 幻影读 |
---|---|---|---|
READ-UNCOMMITTED | √ | √ | √ |
READ-COMMITTED | × | √ | √ |
REPEATABLE-READ | × | × | √ |
SERIALIZABLE | × | × | × |
如何设置和使用事务?
① 设置方式:
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
② 使用方式
START TARNSACTION |BEGIN:显式地开启一个事务。
COMMIT:提交事务,使得对数据库做的所有修改成为永久性。
ROLLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
2.1 读取未提交 READ-UNCOMMITTED
允许读取尚未提交的数据变更,最低的隔离级别,可能导致脏读、幻读或不可重复读。
场景:设置事务隔离级别为读未提交,导致脏读。
2.2 读取已提交 READ-COMMITTED
允许读取并发事务已经提交的数据,可以避免脏读,可能导致幻读或不可重复读。
场景:设置事务隔离级别为读已提交,避免脏读。
场景:设置事务隔离级别为读已提交,导致不可重复读。
2.3 可重复读 REPEATABLE-READ
同一个事务下多次读取结果都是一致的,除非数据是被自己的事务所修改,可以避免脏读、不可重复读,但可能导致幻读。
场景:设置事务隔离级别为可重复读,避免不可重复读。
推荐阅读: