快捷搜索:
来自 网络数据库 2019-09-23 12:15 的文章
当前位置: 67677新澳门手机版 > 网络数据库 > 正文

mvcc多版本达成,InnoDB下关于MVCC的三个标题标分析

 

出自:

这几个是网络朋友 C 在群里问的四个有关MySQL的标题,本篇文章实验测量试验意况为MySQL 5.6.20,事务隔开品级为REPEATABLE-READ ,在示范难题前,大家先谋算测量试验情形。希图一个测量检验表test以及三个存款和储蓄进程循环往test表里面插入记录。

基本知识

 

倘使对于多版本(MVCC)的基础知识,有所了然。InnoDB为了实现多版本的一样读,选用的是依赖回滚段的商酌。

CREATE TABLE test

(

  `id` int(11) primary key not null,

  `name` char(255) 

) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;

 

 

delimiter &&

drop procedure if exists prc_insert;

 

create procedure prc_insert(in  cnt int)

begin

declare i int;

set i=1;

while i < cnt do

    insert into test(id, name) select i,  CONCAT('name',i) from dual;

    

    set i = i 1;

 

end while;

end &&

 

delimiter ;

行结构

 

InnoDB表数据的集体措施为主键聚簇索引。由于接纳索引组织表结构,记录的ROWID是可变的(索引页差别的时候,Structure Modification Operation,SMO),由此二级索引中应用的是(索引键值, 主键键值)的结缘来独一分明一条记下。

在线程ID为14的对话中,开启事务,然后实践查询test的SQL语句

随意聚簇索引,照旧二级索引,其每条记下都含有了八个DELETED BIT位,用于标志该记录是或不是是删除记录。除却,聚簇索引记录还应该有八个系统列:DATA_TRX_ID,DATA_ROLL_PTR。DATA _TRX_ID表示发生方今记录项的职业ID;DATA _ROLL_PT本田CR-V指向当前记录项的undo信息。

 

聚簇索引行结构(与多版本一样读关于的一些,DELETED BIT省略):

mysql> select connection_id() from dual;

 ----------------- 

| connection_id() |

 ----------------- 

|              14 |

 ----------------- 

1 row in set (0.00 sec)

 

mysql> start transaction;

Query OK, 0 rows affected (0.00 sec)

 

mysql> select * from test;

图片 1

 

    二级索引行结构:

 

图片 2

下一场在线程ID为12的对话中,循环往表test里面插入一千000笔录

    从聚簇索引行结构,与二级索引行结构得以看出,聚簇索引中含有版本新闻(事务号 回滚指针),二级索引不分包版本音讯,二级索引项的可见性怎么样决断?上面将会提交。

 

Read View

mysql> select connection_id() from dual;

 ----------------- 

| connection_id() |

 ----------------- 

|              12 |

 ----------------- 

1 row in set (0.00 sec)

 

mysql> call prc_insert(1000000);

Query OK, 1 row affected (8 min 32.11 sec)

InnoDB私下认可的隔绝等第为Repeatable Read (本田UR-V福特Explorer),可重新读。InnoDB在起来叁个TucsonEscort读之前,会创设一个Read View。Read View用于判断一条记下的可知性。Read View定义在read0read.h文件中,当中最入眼的与可知性相关的属性如下:

 

    dulint    low_limit_id;    /* 事务号 >= low_limit_id的记录,对于眼下Read View都以不可知的 */

 

    dulint    up_limit_id;    /* 事务号 < up_limit_id ,对于当下Read View都是可知的 */

在实践循环插入的这段时光里(SQL试行供给几分钟时间),我们在线程ID 为14的对话中屡屡实施select * from test那几个SQL语句,你会发掘该SQL的实践时间变长。那么引起SQL语句实践时间变长的来由是怎么着吗? 怎么样解释得通吗?

    ulint    n_trx_ids;    /* Number of cells in the trx_ids array */

 

    dulint*    trx_ids;    /* Additional trx ids which the read should

 

                not see: typically, these are the active

图片 3

                transactions at the time when the read is

 

                serialized, except the reading transaction

刚初阶探究的时候,感到MySQL会像ORACLE那样会在UNDO的回滚段中发生大批量UNDO记录,最终形成SQL语句会像ORACLE那样发生额外的一致性读,产生额外的IO,进而致使实践时间变长。 后边测量试验发掘,其实对于MySQL来说,INSERT操作在专业提交前只对近来作业可知,由此发生的Undo日志能够在作业提交后直接删除,而这里使用是全自动提交情势。用“MySQL手艺内情:InnoDB存款和储蓄引擎”里面提供的剧本py_innodb_page_info.py测量试验表明。也是真的如此(UNDO日志的分寸变化非常的小,时而增加,时而变小)。其实MySQL里面多版本出现调节(MVCC)的贯彻机制跟Oracle还是不一致的。不可能优孟衣冠Oracle下的那套理论。

                itself; the trx ids in this array are in a

 

                descending order */

 

dulint    creator_trx_id;    /* trx id of creating transaction, or

[root@DB-Server kerry]# python py_innodb_page_info.py /data/mysql/ibdata1

Total number of page: 4864:

Insert Buffer Free List: 32

Insert Buffer Bitmap: 1

System Page: 130

Transaction system Page: 1

Freshly Allocated Page: 1326

Undo Log Page: 3224

File Segment inode: 6

B-tree Node: 142

File Space Header: 2

[root@DB-Server kerry]# python py_innodb_page_info.py /data/mysql/ibdata1

Total number of page: 4864:

Insert Buffer Free List: 32

Insert Buffer Bitmap: 1

System Page: 130

Transaction system Page: 1

Freshly Allocated Page: 1326

Undo Log Page: 3223

File Segment inode: 6

B-tree Node: 143

File Space Header: 2

[root@DB-Server kerry]# python py_innodb_page_info.py /data/mysql/ibdata1

Total number of page: 4864:

Insert Buffer Free List: 32

Insert Buffer Bitmap: 1

System Page: 130

Transaction system Page: 1

Freshly Allocated Page: 1326

Undo Log Page: 3213

File Segment inode: 5

B-tree Node: 154

File Space Header: 2

[root@DB-Server kerry]# python py_innodb_page_info.py /data/mysql/ibdata1

Total number of page: 4864:

Insert Buffer Free List: 32

Insert Buffer Bitmap: 1

System Page: 130

Transaction system Page: 1

Freshly Allocated Page: 1326

Undo Log Page: 3205

File Segment inode: 5

B-tree Node: 162

File Space Header: 2

[root@DB-Server kerry]# python py_innodb_page_info.py /data/mysql/ibdata1

Total number of page: 4864:

Insert Buffer Free List: 32

Insert Buffer Bitmap: 1

System Page: 130

Transaction system Page: 2

Freshly Allocated Page: 1326

Undo Log Page: 3240

File Segment inode: 5

B-tree Node: 127

File Space Header: 1

                (0, 0) used in purge */

 

回顾的话,Read View记录读起来时,全部的移动工作,那些事务所做的更改对于Read View是不可知的。除却,全体其余的小于创设Read View的事务号的兼具记录均可知。可知包含两层意思:

其实InnoDB的多版本出现调节(MVCC),“高质量MySQL”那本书中有诸有此类一段描述:

  • 记录可知,且Deleted bit = 0;当前记下是可知的卓有效能记录。

  • 笔录可知,且Deleted bit = 1;当前记下是可知的删减记录。此记录在工夫务起首此前,已经去除。

 

测验方法:

 

–create table and index

InnoDB的MVCC,是通过每行记录后边保存的多少个暗藏的列来完毕的。 那多个列三个封存了行的创始时间,一个保存行的晚点时间(或删除时间),当然存款和储蓄的并非事实上的年华值,而是系统版本号(System version number),每发轫三个新的工作,系统版本号都会自行递增,事务先导每日的系统版本号会作为专门的学业的本子号,用来和询问到的每行记录的版本号进行比较。下边看一下在REPEATABLE READ隔绝等第下, MVCC是怎么具体操作的。

create table test (id int primary key, comment char(50)) engine=InnoDB;

 

create index test_idx on test(comment);

SELECT

–Insert

 

insert into test values(1, ‘aaa’);

InnoDB会依照以下四个原则检查每行的笔录:

insert into test values(2, ‘bbb’);

 

–update primary key

    a.  InnoDB只查找版本早于当前业务版本的数码行(也正是,行的种类版本号小于或等于职业的系统版本号),那样能够确认保障业务读取的行,要么是在职业初始前已经存在的,要么是业务本人插入或更改过的。

update test set id = 9 where id = 1;

    b.  行的删除要么未定义,要么大于当前事务版本号。那足以确认保障专业读取到的行,在职业最早从前未被剔除。

–update non-primary key with different value

 

update test set comment = ‘ccc’ where id = 9;

独有符合上述多少个尺码的笔录,技能回来作为查询结果。

–update non-primary key with same value

..............................................

update test set comment = ‘bbb’ where id = 2 and comment = ‘bbb’;

 

–read隔断品级

实则至少从MySQL 5.5之后, 每一行开首额外包括四个遮盖字段,并不是叁个字段(未有考查高品质MySQL首要呈报哪个MySQL版本)。

repeatable read(RR)

 

测量检验结果

 

update primary key

·         6字节的政工ID(DB_TRX_ID)字段: 用来标志如今贰回对行当记录做修改(insert|update)的事情的标志符, 即最终贰回修改(insert|update)本行记录的事体ID。

代码调用流程:

    至于delete操作,在InnoDB看来也可是是一回update操作,更新行中的三个特别位将行表示为deleted, 并不是真正删除。

ha_innobase::update_row -> row_update_for_mysql -> row_upd_step -> row_upd -> row_upd_clust_step -> row_upd_clust_rec_by_insert -> btr_cur_del_mark_set_clust_rec -> row_ins_index_entry

 

简易的话,就是将cluster index的旧记录标识位删除;插入一条新记录。该语句奉行完以往,数据结构如下:

·         7字节的回滚指针(DB_ROLL_PT瑞鹰)字段: 指写入回滚段(rollback segment)的 undo log record (撤销日志记录记录)。

图片 4

    如若一行记录被更新, 则 undo log record 包罗 '重新建立该行记录被更新以前内容' 所不可不的音信。

 老版本依然存款和储蓄在聚簇索引之中,其DATA_TRX_ID被设置为1811,Deleted bit设置为1,undo中记录了前镜像的业务id = 1809。新版本DATA_TRX_ID也为1811。通过此图,还是可以够发掘,固然新老版本是一条记下,可是在聚簇索引中是经过两条记下来标志的。同一时间,由于更新了主键,二级索引也要求做相应的换代(二级索引中包括主键项)。

本文由67677新澳门手机版发布于网络数据库,转载请注明出处:mvcc多版本达成,InnoDB下关于MVCC的三个标题标分析

关键词: