导读目录:
1 早期结论… 3
2 测试一:死锁检测… 4
3 测试二:cursor测试… 6
4 测试三:external_lock测试… 6
5 测试四:杂项测试… 6
6 测试五:autocommit测试… 7
7 测试六:unlock tables测试… 9
8 测试七:锁等待超时测试… 9
9 测试八:store_lock函数… 10
10 测试九:InnoDB两阶段提交… 12
10.1 autocommit = ON.. 12
10.2 autocommit = off. 14
10.3 flush_at_trx_commit参数处理… 15
11 测试十:InnoDB crash recovery. 15
11.1 recovery的三种模式… 16
12 测试十一:index coverage scan?… 18
13 测试十二:mini transaction.. 18
14 测试十三:事务开始… 19
14.1 autocommit=ON.. 19
14.2 autocommit=OFF. 19
14.3 Innodb内部事务… 20
15 测试十四:insert ignore测试… 20
16 测试十五:auto_increment. 21
17 测试十六:数据格式转换… 23
18 测试十七:innodb加载表数据字典… 23
19 测试十八:scan测试… 24
20 测试十九:加锁等待… 26
21 测试二十:mysql定位table. 27
22 测试二十一:如何做join.. 28
23 测试二十二:latch & lock holding latch.. 28
24 测试二十三:MySQL上层加锁逻辑… 29
25 测试二十四:get_share & free_share. 30
26 测试二十五:Insert on duplicate update. 31
27 测试二十六:purge测试… 32
28 测试二十六(cont.): purge测试续… 32
29 测试二十七:blob & blob purge. 34
30 测试二十八:HA_READ_KEY_EXACT. 35
31 测试二十九:offline_ddl/fast_idx_create. 37
32 测试三十:partition & innoplugin.. 39
33 测试三十一:vs 2008 + mysql5.5. 41
34 测试三十二:ntse online add index. 42
35 测试三十三:group log write & flush.. 43
36 测试三十三(cont.): mutex & event. 44
37 测试三十四:innodb readview测试… 48
38 测试建表三十五: utf8 21845 vs 21846. 49
39 测试三十六:innodb表元数据并发控制… 50
40 测试三十七:ntse引擎Table模块… 53
41 测试三十八:truncate vs drop. 56
42 测试三十九:加锁逻辑 innodb vs ntse. 56
43 测试四十:mysql+ntse实现update. 57
44 测试四十一:Halloween,RBR. 58
45 测试四十二:innodb无主键表… 61
本文档主要内容:用于分析InnoDB源代码
目的:
设计TNT事务型引擎,作为参考
实验:
create table tlock (id int primary key, comment varchar(200));
insert into tlock values(1, ‘aaaaaaaaaaaaaaaaa’);
insert into tlock values(2, ‘bbbbbbbbbbbbbbb’);
insert into tlock values(100, ‘zzzzzzzzzzzzzzzzzz’);
insert into tlock values(1000,’AAAAAAAAAAAA’);
版本:
select version(); 5.1.49-debug-log
存储引擎:InnoDB
早期收获:
一、基本了解innodb锁表模块功能,与mysql交互,表锁,行锁,加锁,放锁,死锁检测,函数调用逻辑,TNT锁表模块可以参考。
二、基本了解innodb事务模块功能,与上层交互接口,调用方式,事务提交选择,TNT事务模块原型已经有底。
三、基本了解innodb XA事务,crash recovery流程,与上层接口交互,恢复逻辑,TNT支持binlog的二阶段提交,恢复功能可以做出。
四、了解部分函数功能,测试版本innodb的不足之处,可以在实现TNT引擎过程中,加以避免。
五、其他…
1.早期结论
测试结果比较乱,看起来会比较累,但是基本上说明了innodb的事务/加锁/二阶段提交/crash recovery流程。对设计TNT引擎,十分有帮助。
a) 表锁,在statement第一次取记录前加(LOCK_IS, LOCK_IX);external_lock函数,仅仅维护表计数(上层mysql对表加锁的计数),而不是真正加锁。
b) 行锁,根据模式,对记录加锁(LOCK_S, LOCK_X)
c) 在加行锁之前,必须保证表级意向锁已经加上
d) autocommit = ON,Innodb Lock tables不做任何操作,不对表加锁;但是mysql上层会对表加锁。
e) autocommit=OFF,Innodb Lock tables对表加锁(LOCK_S, LOCK_X);同时mysql上层也会对表加锁。
f) mysql上层会加表锁,而且保证加锁不会产生死锁;innodb执行statement过程中,只会加LOCK_IS,LOCK_IX表锁锁,不会加LOCK_S,LOCK_X表锁;LOCK_S,LOCK_X表锁,只会在autocommit=OFF时,发出LOCK TABLES指令是才加。innodb没有锁升级。
g) 表意向锁(LOCK_IS,LOCK_IX)的加锁,延迟到statement取第一条记录之前。
2. external_lock函数功能
a) external_lock函数,顾名思义,外部的锁。对于innodb来说,外部的锁就是上层mysql的锁。statement开始时,mysql上层会对statement涉及到的表加锁,同时调用external_lock函数通知innodb(每个表都调用一次),external_lock函数记录下上层加表锁的数量;statement结束时,mysql上层释放statement涉及到的表锁,同时调用external_lock函数通知innodb,每调用一次,计数减减,当计数到0时,根据当前autocommit设置,判断是否需要自动提交事务(因为mysql上层并不会自动调用commit函数,触发事务提交)。
3.功能测试
a) 加锁流程,每个测试都有加锁流程
b) commit,放锁流程,详见测试4,测试6
c) 事务开始时与mysql的交互,详见测试13
d) 死锁检测流程,详见测试1
e) Lock节点组织、定位,详见测试4
f) autocommit参数的影响,详见测试4,测试5
g) lock tables & unlock tables,详见测试6
h) 加锁等待超时 vs 不超时,详见测试7
i) store_lock函数功能,见测试8,不详尽
j) innodb二阶段提交支持,见测试9
k) innodb的crash recovery,见测试10
l) innodb如何实现auto increment,见测试15
m) mini transaction的功能,见测试12
a) 在我测试的版本中,一个kernel mutex,保护server,trx,query threads,lock table,保护的资源太多,会是瓶颈之一。
b) Innodb二阶段提交,开启binlog,group commit就被自动禁用。极大的增加了fsync调用,降低了并发系统性能,prepare_commit_mutex。
c) 死锁检测做的不是很高效。(当然这也与多版本并发控制有关,加锁概率小,锁不会太多)
d) 放锁时,唤醒操作也不是很高效。(挨个遍历需要唤醒的Lock,每个lock又需要与链表前面的lock比较是否冲突)
e) 在发出lock tables命令之后,select … lock in share mode仍旧需要对行记录加锁
f) 锁等待超时innodb_lock_wait_timeout就报错返回,有时会对用户造成困扰 (当然,mysql的应用环境下,都是短小事务,遇见此报错的概率很小)