MySQL MVCC实现

数据多版本(MVCC)是MySQL实现高性能的一个主要的一个主要方式,通过对普通的SELECT不加锁,直接利用MVCC读取指版本的值,避免了对数据重复加锁的过程,今天我们就用最简单的方式,来分析下MVCC具体的原理,先解释几个概念:

隐藏列

在分析MVCC原理之前,先看下InnoDB中数据行的结构:

row

在InnoDB中,每一行都有2个隐藏列DATA_TRX_ID和DATA_ROLL_PTR(如果没有定义主键,则还有个隐藏主键列):

  1. DATA_TRX_ID表示最近修改该行数据的事务ID
  2. DATA_ROLL_PTR则表示指向该行回滚段的指针,该行上所有旧的版本,在undo中都通过链表的形式组织,而该值,正式指向undo中该行的历史记录链表

整个MVCC的关键就是通过DATA_TRX_ID和DATA_ROLL_PTR这两个隐藏列来实现的。

继续阅读

MySQL异常锁冲突一例

背景

MySQL版本:5.7, 隔离级别:RR

测试表结构:

CREATE TABLE `sbtest1` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`k` int(11) NOT NULL DEFAULT ‘0’,

`c` char(120) NOT NULL DEFAULT ”,

`pad` char(60) NOT NULL DEFAULT ”,

PRIMARY KEY (`id`),

) ENGINE=InnoDB

标准的sysbench测试表,由于二级索引跟本次分析无关,所以没有创建。

整个表大概有50w行记录,表中的数据记录如下:

id k c pad
100 250731 xxx xxx
101 251240 xxx xxx
150 249472 xxx xxx
151 251323 xxx xxx

继续阅读

InnoDB recovery详细流程

InnoDB如果发生意外宕机了,数据会丢么?对于这个问题,稍微了解一点MySQL知识的人,都会斩钉截铁的回答:不会!为什么?他们也会毫不犹豫的说:因为有重做日志(redo log),数据可以通过redo log进行恢复。回答得很好,那么InnoDB怎样通过redo log进行数据的恢复的,具体的流程是怎样的?估计能说清楚这个问题的人剩的不多了,更深入一点:除了redo log,InnoDB在恢复过程中,还需要其他信息么?比如是否需要binlog参与?undo日志在恢复过程中又会起到什么作用?到这里,可能很多人会变得疑惑起来:数据恢复跟undo有半毛钱的关系?
其实,InnoDB的数据恢复是一个很复杂的过程,在其恢复过程中,需要redo log、binlog、undo log等参与,这里把InnoDB的恢复过程主要划分为两个阶段,第一阶段主要依赖于redo log的恢复,而第二阶段,恰恰需要binlog和undo log的共同参与,接下来,我们来具体了解下整个恢复的过程。
第一阶段
第一阶段,数据库启动后,InnoDB会通过redo log找到最近一次checkpoint的位置,然后根据checkpoint相对应的LSN开始,获取需要重做的日志,接着解析获取的日志并且保存到一个哈希表中,最后通过遍历哈希表中的redo log信息,读取相关页进行恢复。
InnoDB的checkpoint信息保存在日志文件中,即ib_logfile0的开始2048个字节中,checkpoint有两个,交替更新,checkpoint与日志文件的关系如下图:
1
checkpoint位置

继续阅读