事务指的是构成单一逻辑工作单元的操作集合,事务处理是被设计用来维持系统的完整性在一个已知的,一致的状态
事务隔离级别
读取未提交内容
事务可以看到其他事务尚未提交的修改,可能会引发“脏读”现象
读取提交内容
对选定对象的写锁一直保持到事务结束,但是读锁在操作完成后马上释放,可能会引发“不可重复读”现象
可重复读
对选定对象的读锁和写锁一直保持到事务结束,可能会引发“幻读”现象
可串行化
这一隔离级别指的是“要求在选定对象上的读锁和写锁保持直到事务结束后才能释放”,并通过范围锁防止幻读现象的产生
“不可重复读和幻读的区别:不可重复读重点在于update和delete,而幻读的重点在于insert;在可重读隔离级别中,事务A在读取数据的同时对数据进行加锁,使得其他事务无法修改该部分数据;但是依然可以insert数据;导致事务A会出现“幻读”的现象
如何解决事务产生的问题
- 脏读
读取数据使用共享锁,在修改数据时使用排他锁,并在事务提交后释放排他锁;但是因为共享锁是在读取完毕后释放,从而会引发“不可重复读”问题
- 不可重复读
同样的,会在读取数据时使用共享锁,而在修改数据时使用排他锁,并在事务提交后释放排他锁和共享锁,使得数据在事务内能够重复读
- 幻读
幻读则能够通过间隙锁,阻止其他事务向区间内插入数据,MySQL中则通过MVCC机制解决这一问题
MVCC多版本控制
MVCC是数据库在高并发场景下的事务解决方案,同时能够保证数据库读写性能。
数据行结构
- DATA_TRX_ID:表示最近修改该行数据的事务ID
- DATA_ROLL_PTR:表示该行回滚段的指针,记录行数据的历史版本链表
一致读
在数据读操作中,并不是直接读取当前数据,而是通过事务ID的方式读取历史数据,防止“不可重复读”现象产生,这叫做快照读。
并发写
在对数据写操作中,通过行锁的方式依然会出现“幻读”现象;所以MVCC机制将行锁+间隙锁组合得到Next-Key锁,这样能够防止区间内数据插入。
事务日志
在MySQL使用场景下,事务日志包括Undo/Redo log和bin log
MySQL事务提交过程
- 执行数据操作,并写入内存
- 写入Undo/Redo log,处于prepare状态
- 写入bin log
- 提交事务,处于commit状态
“在单体数据库中使用事务提交,理论上是能够不写入binlog,因为InnoDB本身就具有事务回滚机制;但是binlog是归档日志,可以在分布式数据库中节点复制
崩溃恢复如何判断事务可提交
- redo log内完整,并且有commit状态标识
- redo log完整并处于prepare状态,bin log完整
undo/redo log和bin log的区别
- undo/redo log是Inno DB用于实现事务机制的关键,具有crash-safe的特性
- bin log是归档日志,不会进行循环写,可用于MySQL复制
- undo log保存原数据,主要用于事务回滚场景
XA规范
XA规范描述了全局的事务管理器与局部的资源管理器之间的接口,允许多个资源能够在同一事务内执行,实现分布式事务处理
两阶段提交协议
- 节点S发起事务T,并由事务协调器C发起询问,检查事务T所有相关节点是否处于就绪状态
- C通过日志查看所有参于事务T的节点是否处于就绪状态,并进行事务提交或中止操作
实现分布式锁
- 基于数据库的方式:维护锁表实现锁的获取和释放
- 基于redis的方式:通过setnx实现加锁和锁的释放
- 基于zookeeper的方式:在lock目录下维护顺序节点
本文使用 mdnice 排版