MySQL 事务
-
时间: 2017-11-26 09:16:57
-
参考:
事务特性#
-
原子性:数据库操作要么执行成功,要么执行失败回滚。
-
一致性:事务必须保证数据库从一个一致性状态到另一个一致性状态,比如说A,B一共有200元,在事务过程中,无论A、B怎么转账,A、B的还是一共有200元。
-
隔离性: 并行操作数据库的事务之间不能相互干扰, 即对于任意事务1,来说事务2要么在1之前完成,要么在1之后完成。
-
持久性:事务提交之后,数据肯定会被保存子在磁盘中。
隔离性解决的问题#
-
脏读: 事务1修改数据,之后事务1回滚。事务2在事务1
回滚之前修改数据之后
,在此基础上对数据进行修改,之后提交事务。 -
不可重复读:解决脏读,事务1执行两次查询,在两次查询之间,事务2对查询的数据进行了修改(增、删、改),并提交了事务,导致事务1两次查询产生的结果不一样。
-
幻读:解决不可重复读,事务1执行两次查询一次操作,事务2在两次查询之间插入数据数据,由于不可重复度的原因,事务1第二次查到的数据和第一次查到的数据相同,但是事务1执行插入和事务2插入的数据相同数据时会失败。
事务隔离级别#
以A和B两个不同的事务为例,事务A读取数据,事务B更新数据,把事务B的执行分为4个阶段
1 |
|
-
Read Uncommit(读未提交):可能发生脏读、不可重复度和幻读。
- 在此隔离级别下:事务B执行
S2
之后,事务A读取数据,会读取到事务B第一次更新后的数据,此时事务B还未提交,出现脏读的情况。
- 在此隔离级别下:事务B执行
-
Read Commit(读提交): 可避免脏读,可能发生不可重复度和幻读。
-
在此隔离级别下:
- 事务B执行
S2
之后,事务A读取数据,会读取到事务B开始时的原始数据,避免脏读的情况。 - 事务B执行
S5
之后,事务A再次读取数据(事务A在第一次读取之后没有提交),此时读取的数据和第一次读取的数据不一致,出现了不可重复读的情况。
- 事务B执行
-
-
REPEATABLE READ(可重复读):执行update更新语句时,会在更新时所有已提交的事务产生最新的记录上进行更新,有可能出现更新的实际内容和事务内查询出的内容不一致的情况。(InnoDB 通过版本解决幻读)。
- 事务B执行 S2 之后,事务A读取数据,会读取到事务B开始时的原始数据,避免脏读的情况。
- 事务B执行 S2 之后,事务A查询一次总数量。
- 事务B执行 S5 之后,事务A再次读取数据(事务A在第一次读取之后没有提交),此时读取的数据和第一次读取的数据一致的,避免不可重复读的情况(快照机制)。
-
事务B执行 S5 之后,事务A查询一次总数量,和前面查询结果相同,事务A执行一次
update all
操作,此时事务B提交的内容也会被更新(在所有已提交事务产生的最新版本的数据上进行更新),之后事务A再执行一次查询总数操作,此时查询的数量比前两次多一。START TRANSACTION; SELECT * FROM person; update person SET age = age + 1 WHERE name = 1; COMMIT; START TRANSACTION; SELECT * FROM person; update person SET age = age + 1 WHERE name = 1; COMMIT;
上面两个事务不论以什么的顺序执行,全部提交之后,age的值会增加二,符合常理。
-
SERIALIZABLE:串行执行。可避免脏读,不可重复读,幻读。
- 所有的事务串行执行,由于同时只有一个事务执行,保证事务再执行的时候,没有其它事务会会影响次失的操作,效率很低。
MySql事务机制#
undo 日志#
记录执行的语句,在出错的时候进行数据回滚。回滚的时机:
- 执行
rollback
回滚。 - 数据库服务重启之后,回滚未完成的事务。