MySQL中的MVCC

一、 解决方案:

解决读写的并发问题可以使用 MVCC(多版本并发控制) 和 锁机制来解决。
MVCC方式(也称为快照读)的性能高于 加锁方式, 加锁方式需要排队,影响效率。

二、MVCC的实现原理

MVCC主要依赖于 数据库记录的三个隐藏字段、 undo.log 和 readView 来实现。

1、三个隐藏字段

         (1) DB_TRX_ID : 最后一次操作的事务id;
         (2) DB_ROLL_PTR:回滚的指针,执行上一个版本的记录,配合undo.log 使用
         (3) DB_ROW_ID : 隐藏主键,如果表中没有主键才会创建。

2.undo.log (回滚日志)

所有事务进行的修改都会先记录到这个回滚日志中,如 insert、delete、 update 就会产生便于回滚的数据记录,写入到回滚日志中。
当insert,执行提交后,会马上删除回滚记录, delete、update会保留,用于快照读时使用(快照读-不加锁读,读取的数据记录是可见版本)
当不同事务都并发修改同一条记录时 ,会产生一条undo版本链,链表的内容时一条条行记录,用roll_pointer指向下一条记录。

3.Readview(读视图)

是快照读执行是MVCC读取数据的依据,
里面包括4个核心字段
m_ids :当前活跃的事务id集合
min_trx_id:最小活跃事务id
max_trx_id:预分配事务id(当前事务id+1,事务id是自增的)
createor_trx_id: ReadVieiw创建者的事务id

不同隔离级别的ReadView生成机制不同,
Readcommited:每次select 都会生成一个ReadView
Repeatable Read: 只有当前事务,第一个select会生成ReadView,后面复用。

MVCC在可重复的模式小,不仅解决的事务并发的重复读问题,还可解决的大部分幻读问题。

具体实现:

InnoDB 通过数据行的 DB_TRX_ID 和 Read View 来判断数据的可见性,如不可见,则通过数据行的 DB_ROLL_PTR 找到 undo log 中的历史版本,通过版本链的数据访问规则。来读取记录。每个事务读到的数据版本可能是不一样的,在同一个事务中,用户只能看到该事务创建 Read View 之前已经提交的修改和该事务本身做的修改。

基于数据库表中隐藏字段 tx_id来判断,当tx_id,小于min_trx_id(最小活跃事务id)时,min_trx_id。
如果记录的 trx_id 值大于等于 Read View 中的 max_trx_id 值,表示这个版本的记录是在创建 Read View 后才启动的事务生成的,所以该版本的记录对当前事务不可见。
如果恰好在两者之间,要判断tx_id是否在m_ids(当前活跃事务id集合),不在则说明事务已提交,该版本可见。

三、锁机制

1、按数据操作方式分类

   (1) 读锁
 (2)写锁
 只有 读锁 与 读锁 兼容

2. 数据操作粒度划分,表锁,行级锁,页锁

(1)表锁:
S .X . 意向锁、元数据锁。
使用:
LOCK TABLE 表名 READ;
LOCK TABLE 表名 WRITE;
意向锁:
给更大级别加锁(向上加锁), 如:对行加锁,系统自动会给,表加锁。
解决其他事务来 对加锁 时需要一条判断是否加锁。

元数据锁,系统自动加,当增删改查时会自动加MDL读锁, 修改表结构时加MDL写锁.

(2)行锁
增删改操作会自动加锁
共享锁: lock in share mode;/ FOR SHARE;
排他锁: FOR UPDATE;

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值