三分钟解读MVCC原理

MVCC实现原理主要是依赖记录中的 3个隐式字段undo日志Read View 来实现的。

某条记录

name

grade

DB_ROW_ID

DB_TRX_ID

DB_ROLL_PTR

zhangsan

A

1

5

null

三个隐式字段:

DB_ROW_ID:隐含的自增ID(隐藏主键)

DB_TRX_ID:记录最近修改这条记录的事务ID

DB_ROLL_PTR:回滚指针,指向这条记录的上一个版本

undo log:

将之前的操作都记录下来,适当时候进行回滚。(通过回滚指针进行回滚)

比如事务6将grade更改为A+:

name

grade

DB_ROW_ID

DB_TRX_ID

DB_ROLL_PTR

zhangsan

A+

1

6

0x123456

name

grade

DB_ROW_ID

DB_TRX_ID

DB_ROLL_PTR

zhangsan

A

1

5

null

ReadView

读视图,即事务进行快照读时刻,生成的数据库记录的快照。

可以将ReadView简化出三个属性:

list:记录生成ReadView时刻,活跃的事务ID

up_limit_id:list中最小的ID

low_limit_id:生成ReadView时刻,下一个未被分配的事务ID

基本流程

  • 当某事务查看记录时候,先拿该记录的DB_TRX_ID与up_limit_id(list中最小的ID)比较,如果DB_TRX_ID<up_limit_id,满足可见性,说明当前事务能看到DB_TRX_ID的记录,如果不小于进入下一轮;
  • 拿该记录的DB_TRX_ID与low_limit_id(生成ReadView时刻,下一个未被分配的事务ID)比较,如果大于等于,则说明不可见,回滚指针将回滚上一个版本,重新进行判断。如果小于进入下一轮判断;
  • 如果DB_TRX_ID在list(活跃事务中),则不可见,回滚指针回滚,不在的话,说明可见。

为了进一步让大家了解MVCC原理,在下面我举了个例子

启动事务A,事务id为20,ReadView如下:

当事务A查看下面这条记录:

由于19>18,进入下一轮判断;

19 !>= 23,进入下一轮判断;

19 in List,回滚指针,选择该记录上一个版本再进行判断;

17<18,可见,说明事务A可以看到DB_TRX_ID=17的版本。

在这里,我利用一个代表DB_TRX_ID的数轴,绿色为可见,红色为不可见,可以利用这个数轴作为万能公式

### 多版本并发控制 (MVCC) 原理解释 #### 数据库中的事务隔离级别与MVCC的关系 为了确保数据库系统的高并发性和数据一致性,多版本并发控制(MVCC)通过为每个事务提供一个特定时间点的数据快照来工作。这意味着当一个新的事务启动时,它会基于其开始的时间点获得一份当前所有记录的状态副本[^3]。 #### MVCC的核心概念 - **隐藏列**:在支持MVCC的存储引擎中,每条记录都隐含着两个额外字段——创建时间和删除时间戳。这些时间戳不是实际的日志时间而是逻辑上的序列号,代表某个事务ID。 - **非锁定读取**:对于大多数查询而言,默认情况下它们是非锁定性质的操作;也就是说,除非显式指定了独占锁或其他类型的锁定语句外,普通的`SELECT`命令不会阻止其他进程对该表项进行更新或插入新行[^1]。 - **可见性规则**:决定哪些版本应该被呈现给正在运行中的各个事务。具体来说,如果一条记录是在某次事务之前生成并提交过的,则这条记录对这个事务是可见的;反之则不可见。这种机制有效地防止了脏读、幻影读等问题的发生[^2]。 #### 实现细节 以InnoDB为例说明其实现方式: - 当执行DML操作如INSERT, UPDATE 或 DELETE 时,除了改变现有元组之外还会标记旧版本的有效期以及新增加的新版本的信息; - 对于每一个新的写入动作都会分配唯一的递增事务编号作为标识符,并将其关联至相应的变更上; - 查询过程中利用上述提到的时间戳来进行过滤判断,从而返回最合适的那套历史数据集给请求方。 ```sql -- 插入新纪录的同时设置create_ts和delete_ts初始值 INSERT INTO table_name (data_column, create_ts, delete_ts) VALUES ('example', CURRENT_TIMESTAMP(), NULL); -- 更新已有记录时复制原版并更改状态标志位 UPDATE table_name SET data_column='new_value', old_version=create_ts, new_version=CURRENT_TIMESTAMP(), deleted=TRUE WHERE id = specific_id; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值