1 事务

数据库事务是指作为单个逻辑工作单元的一系列操作的集合,具有ACID特性。

1.1 原子性(Atomicity)

整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。

  • REDO LOG
  • UNDO REC

1.2 一致性(Consistency)——目标

事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。一致性要求事务执行完成后,将数据库从一个一致状态转变到另一个一致状态。

1.3 隔离性(Isolation)

并发事务所做的修改,与任何其他的并发事务所做的修改相互隔离。每个事务的执行效果与系统中只有该事务的执行效果一样。

  • 4种隔离级别,由高到低分别为:Read uncommitted(读未提交) 、Read committed (读已提交)、Repeatable read (重复读)、Serializable (序列化)。
产品事务隔离级支持情况
Oracleread committed/serializable
InnoDBALL
SQL ServerALL + READ COMMITTED SNAPSHOT
Infomix不支持serializable,last committed read
DM4~DM6ALL
DM7read uncommitted/read committed/serializable
DM8read uncommitted/read committed/serializable

1.4 持久性(Durability)

事务提交(COMMIT)之后,该事务对数据库所作的更改便持久的保存在数据库之中,不会丢失。

  • WAL(Write Ahead Log)

2 MVCC:Multi-Version Concurrent Control(多版本并发控制)

在MVCC协议下,每个读操作会看到一个一致性的snapshot。MVCC允许数据具有多个版本,这个版本可以是时间戳或者是全局递增的事务ID,在同一个时间点,不同的事务看到的数据是不同的。

MVCC提供高并发的读写访问性能,是提升数据库并发性能的一种重要技术手段。

主要特征:写不会阻塞读,读操作永远不会被阻塞。

2.1 各产品MVCC支持情况

产品MVCC支持情况
SQL ServerCOPY ON WRITE机制,老记录写入临时库
PostgreSQLCOPY ON WRITE机制,老记录写入数据页。记录包含4个隐含字段,VACUUM清理
DB2支持
Informix不支持
DM4~DM6不支持,回滚页是多个事务共享的,非事务独立。
DM6后期版本基于回滚记录表的方式实现,回滚记录写入临时库的特定表中
Oracle回滚记录,行级,SNAPSHOT页。ITL包含:回滚记录地址、事务号、事务状态、SCN等信息
InnoDB回滚记录,行级
DM7/DM8基于回滚记录,回滚记录包含附加字段:TID、RPTR;添加了活动事务视图TRX_VIEW,MAX_TRXID;根据隔离级别分别在事务启动、或者SQL执行前收集;事务独立的回滚页,基于时间规则(UNDO_RETENTION)清理数据(PURGE),慢SQL优化

2.2 多版本读策略

  1. 收集TRX_VIEW,MIN_ACTIVE_ID,NEXT_ID;
  2. 根据记录上的TRX_ID,判断记录可见性;
  3. TRX_ID >= NEXT_ID,不可见;
  4. TRX_ID == SELF_ID,可见;
  5. TRX_ID < MIN_ACTIVE_ID,可见;
  6. TRX_ID不在TRX_VIEW中,可见;TRX_ID位于TRX_VIEW中,不可见;
  7. 根据RPTR查找回滚记录,构造前一个版本的数据,重复这个判断,直到找到可见记录;

2.3 基于时间戳的可见性判断策略

使用TRX_VIEW_MODE参数控制可见性模式,在事务提交时更新CMTSEQ,事务或SQL启动时获取时间戳SNAP_CMTSEQ。维护一个全局数组CMTARR,可直接根据TRX_ID定位。事务启动时,设置CMTARR对应位置为0,表示事务启动未提交。

  • 可见性判断:

    • 根据TRX_ID从CMTARR获取CMTSEQ
    • SNAP_CMTSEQ >= CMTSEQ,可见
    • SNAP_CMTSEQ < CMTSEQ,不可见
  • DSC集群结合时间戳和TRX VIEW两种模式:

    • 本地事务根据INI参数控制
    • 远程节点事务采用TRX VIEW模式

2.4 多版本写策略

多版本写策略中,数据可见原则与多版本读相同:

  • 如果要写的记录对自己可见,则更新之,产生一个新的版本,TRX_ID为自己的事务ID,老版本保存到回滚记录中
  • 如果要写的记录对自己不可见,不会向回找到记录的历史版本,因为更新必须在最新的版本上进行
  • 不可见时,对占据当前版本的事务TID上一把X锁,这个X锁必然与那个事务启动时对自己的TID上的X锁冲突,导致当前事务被挂起,直到占据数据的事务提交或者回滚为止

2.5 阻塞事务结束后的策略

  • 如果并发的阻塞事务进行了回滚,被阻塞的事务无论在何种隔离级下都可以继续其写操作。
  • 如果并发的阻塞事务进行了提交,读提交级别的事务可以继续执行:(1)更新可见视图;(2)重新执行更新流程。
  • 串行化级别的事务则报“串行化事务被打断”错误。原因:并发事务对数据库进行的修改破坏了该事务的串行化要求。

3 数据库

锁(LOCK)主要用于管理数据库中表、记录等共享资源的并发访问。锁模式包括 X/S/IX/IS

3.1 封锁模式兼容性

ISIXSX
ISYYYN
IXYYNN
SYNYN
XNNNN

3.2 数据库锁实现方式

数据库实现方式
Oracle没有行锁,ITL(Interest Transaction List)。
SQL Server以前采用行锁机制,实现MVCC 后不清楚。
PostgreSQL没有行锁,利用隐藏字段
InnoDB行锁,GAP锁,十分复杂
DM4~DM6读上IS锁,写上IX,ROWID为封锁对象,SERALIZABLE范围锁
DM7/DM8对象锁、TID锁、LATCH封锁数据页 + 可见性判断 + LOCK、UPDATE/DELETE操作符封锁

3.3 对象锁

  • 使用对象的ID进行封锁
  • IS/IX/S/X/S+IX
  • DML语句执行时,对表进行上锁,协调表级的并发访问。隐含上IS和IX锁。
  • 防止在DML/DDL的过程中,访问对象的定义被修改。不同对象采用不同的封锁类型。

3.4 TID锁

  • 使用事务号进行封锁
  • 事务启动时分配事务号(唯一、递增)
  • 事务启动时创建TID锁,事务结束时释放
  • 事务号保存在记录的TID字段
  • 仅支持X模式
  • 事务号唯一,确保事务启动TID锁不产生冲突
  • TID锁用来协调记录级多版本并发控制

3.5 UPDATE/DELETE操作符封锁

  • X LATCH封锁数据页
  • 读取记录TID字段,判断可见性
  • 不可见记录,进行TID封锁,释放LATCH
  • 封锁成功后(可能出现锁等待),重启流程
  • 冲突事务回滚,继续操作
  • 冲突事务提交
  • 读提交重新执行SQL
  • 串行化直接报串行化冲突错误

3.6 死锁检测机制

悲观策略,事前检测,预防死锁

乐观策略,事后检测,回滚事务,消除死锁

达梦数据库 - 新一代大型通用关系型数据库 | 达梦在线服务平台 (dameng.com)

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐