MySQ事务

并发事务的控制方式有哪些?

Mysql中并发事务的控制就两种 MVCC 。锁可以视作悲观控制方式、MVCC可以视作乐观控制方式。

锁主要是通过显示控制而不是调度,主要是通过读写锁来实现并发控制

共享锁(S锁):又称读锁,允许事务在读取记录的时候共享锁;
排他锁(X锁):又称写锁,不允许在修改记录时共享锁;

读写锁可以做到读读并行,但读写、写写并不能并行;
锁又根据细粒度不同分为表级锁和行级锁。

MVCC

MVCC是多版本并发控制方法,即对一份数据会储存多个版本,通过事务的可见性来保证事务都能看到应该看到的版本。通常会有一个全局版本分配器为每一行分配版本,版本号是唯一的。

InnoDB对MVCC的实现

MVCC的实现依赖于:隐藏字段、Read View、undo log。在内部实现中,InnoDB通过数据行的DB_TRX_ID和Read_view来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本。对于每个事务,用户只能看到这个事务创建Readview之前已经提交的事务。

隐藏字段

在内部,InnoDB为每行数据添加了三个隐藏字段:

  • DB_TRX_ID:表示最后一次插入或更新该行的事务id
  • DB_ROLL_PTR:回滚指针,指向该行的undo log,若该行未被更新,则为空
  • DB_ROW_ID:如果没有设置主键且该表没有唯一非空索引时,InnoDB 会使用该 id 来生成聚簇索引
ReadView
class ReadView {
  /* ... */
private:
  trx_id_t m_low_limit_id;      /* 大于等于这个 ID 的事务均不可见 */

  trx_id_t m_up_limit_id;       /* 小于这个 ID 的事务均可见 */

  trx_id_t m_creator_trx_id;    /* 创建该 Read View 的事务ID */

  trx_id_t m_low_limit_no;      /* 事务 Number, 小于该 Number 的 Undo Logs 均可以被 Purge */

  ids_t m_ids;                  /* 创建 Read View 时的活跃事务列表 */

  m_closed;                     /* 标记 Read View 是否 close */
}

m_low_limit_id:目前出现过的最大事务ID+1,即下一个将被分配的事务ID。大于等于这个ID的数据版本均不可见;

m_up_limit_id:活跃事务的最小ID,小于这个ID的版本均可见,如果活跃事务列表为空,m_up_limit_id = m_low_limit_id;

m_ids:Read View创建时其他未提交的活跃事务ID,不包含当前事务,和过去已经提交过的事务;
m_creator_trx_id:创建该 Read View 的事务ID;

在这里插入图片描述

undo-log

undo-log有两个作用:

  • 当事务回滚时,回到最初修改前的yangz
  • MVCC,当读取数据时,若当前数据被其他事务占领,或者当前版本对该事务不可见,可以通过undo-log读取之前的版本数据。

insert undo log 与update undo log
insert undo log是在inset操作中产生的undo log,因为insert操作只有当前事务本身可见,对其他事务不可见,顾该undo log可以在事务提交后删除;
update undo log是在update与delete中产生的undo log,该操作需要提供MVCC机制,不能在事务提交后就进行删除,而是放入undo log列表,等待purge线程最后进行删除。

数据可见性算法

在selec语句执行之前,会创建一个快照,快照中保存了当前数据库中未提交的活跃事务;
当用户在这个事务中要读取某个记录行的时候,InnoDB 会将该记录行的 DB_TRX_ID 与 Read View 中的一些变量及当前事务 ID 进行比较,判断是否满足可见性条件

  1. 如果DB_TRX_ID < m_up_limit_id,该行记录可见
  2. 如果DB_TRX_ID >= m_low_limit_id,不可见,跳转5
  3. m_ids为空,表面当前事务创建快照之前,该事务已提交,可见
  4. 如果 m_up_limit_id <= DB_TRX_ID < m_low_limit_id,表面快照创建时该行事务处于活跃或者已提交状态,所以就要对活跃事务列表 m_ids 进行查找(源码中是用的二分查找,因为是有序的)
  • 如果在活跃事务列表 m_ids 中能找到 DB_TRX_ID,表明:① 在当前事务创建快照前,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了,但没有提交;或者 ② 在当前事务创建快照后,该记录行的值被事务 ID 为 DB_TRX_ID 的事务修改了。这些情况下,这个记录行的值对当前事务都是不可见的。跳到步骤 5
  • 在活跃事务列表中找不到,则表明“id 为 trx_id 的事务”在修改“该记录行的值”后,在“当前事务”创建快照前就已经提交了,所以记录行对当前事务可见

5.在该记录行的 DB_ROLL_PTR 指针所指向的 undo log 取出快照记录,用快照记录的 DB_TRX_ID 跳到步骤 1 重新开始判断,直到找到满足的快照版本或返回空

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值