数据库原理03|事务管理

154 阅读4分钟

事务指的是构成单一逻辑工作单元的操作集合,事务处理是被设计用来维持系统的完整性在一个已知的,一致的状态

事务隔离级别

  • 读取未提交内容

    事务可以看到其他事务尚未提交的修改,可能会引发“脏读”现象

  • 读取提交内容

    对选定对象的写锁一直保持到事务结束,但是读锁在操作完成后马上释放,可能会引发“不可重复读”现象

  • 可重复读

    对选定对象的读锁和写锁一直保持到事务结束,可能会引发“幻读”现象

  • 可串行化

    这一隔离级别指的是“要求在选定对象上的读锁和写锁保持直到事务结束后才能释放”,并通过范围锁防止幻读现象的产生

不可重复读和幻读的区别:不可重复读重点在于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 排版