Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2924019
  • 博文数量: 199
  • 博客积分: 1400
  • 博客等级: 上尉
  • 技术积分: 4126
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-06 19:06
个人简介

半个PostgreSQL DBA,热衷于数据库相关的技术。我的ppt分享https://pan.baidu.com/s/1eRQsdAa https://github.com/chenhuajun https://chenhuajun.github.io

文章分类

全部博文(199)

文章存档

2020年(5)

2019年(1)

2018年(12)

2017年(23)

2016年(43)

2015年(51)

2014年(27)

2013年(21)

2011年(1)

2010年(4)

2009年(5)

2008年(6)

分类: Mysql/postgreSQL

2013-09-15 11:08:26

MySQL的Innodb也采用了MVCC机制提高并发事务的性能,但在可串行化隔离级别下,测试发现它是完全基于锁的。下面是详细测试结果。
测试方法方法请参考笔者之前的文章:
并发事务下各数据库外部表现实测之一(SQL Server篇)
http://blog.chinaunix.net/uid-20726500-id-3883105.html

1. 测试环境
OS:Windows7
DBMS:MySQL 5.6(Innodb)

2. 测试结果
读未提交


先执行SQL\后执行SQL
同一行查询 非同行查询 整表查询 同一行插入 非同行插入 同一行更新 非同行更新 整表更新 同一行删除 非同行删除 整表删除
单行查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
整表查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
插入

OK(*)

OK

OK(*)

等待(*) OK 等待(*) OK OK(**)
等待(*) OK 等待(*)
单行更新

OK(*)

OK

OK(*)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表更新

OK(*)

OK OK(*)
等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
单行删除 OK(*)
OK

OK(*)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表删除

OK(*)

OK

OK(*)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
OK(*):基于更新后的数据,即发生脏读
OK(**):基于更新前的数据

等待(*):
如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据

读已提交

先执行SQL\后执行SQL
同一行查询 非同行查询 整表查询 同一行插入 非同行插入 同一行更新 非同行更新 整表更新 同一行删除 非同行删除 整表删除
单行查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
整表查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
插入

OK(**)

OK

OK(**)

等待(*) OK 等待(*) OK OK(**)
等待(*) OK 等待(*)
单行更新

OK(**)

OK

OK(**)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表更新

OK(**)

OK OK(**)
等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
单行删除 OK(**)
OK

OK(**)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表删除

OK(**)

OK

OK(**)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
OK(**):基于更新前的数据,查询看到的是执行查询时的快照。
等待(*):
如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据

注:黄色代表和读未提交不同的地方

可重复读

先执行SQL\后执行SQL
同一行查询 非同行查询 整表查询 同一行插入 非同行插入 同一行更新 非同行更新 整表更新 同一行删除 非同行删除 整表删除
单行查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
整表查询 OK OK OK 主键冲突 OK OK OK OK OK OK OK
插入

OK(***)

OK

OK(***)

等待(*) OK 等待(*) OK 等待(*)
等待(*) OK 等待(*)
单行更新

OK(***)

OK

OK(***)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表更新

OK(***)

OK OK(***)
等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
单行删除 OK(***)
OK

OK(***)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表删除

OK(***)

OK

OK(***)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
OK(***):基于事务开始时的数据,查询看到的是事务开始时的快照
等待(*):
如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据。

注1:黄色代表和读已提交不同的地方
注2:红色字体的"等待(*)"是MySQL理得问题的地方可能导致幻读和不可重复读。详细在后面说明

可串行化
先执行SQL\后执行SQL 同一行查询 非同行查询 整表查询 同一行插入 非同行插入 同一行更新 非同行更新 整表更新 同一行删除 非同行删除 整表删除
单行查询 OK OK OK 主键冲突 OK 等待(*)
OK 等待(*)
等待(*)
OK 等待(*)
整表查询 OK OK OK 主键冲突 等待(*) 等待(*)
OK 等待(*)
等待(*)
OK 等待(*)
插入

等待(*)

OK

等待(*)

等待(*) OK 等待(*) OK 等待(*)
等待(*) OK 等待(*)
单行更新

等待(*)

OK

等待(*)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表更新

等待(*)

OK 等待(*)
等待(*) 等待(*) 等待(*) OK 等待(*) 等待(*) OK 等待(*)
单行删除 等待(*)
OK

等待(*)

等待(*) OK 等待(*) OK 等待(*) 等待(*) OK 等待(*)
整表删除

等待(*)

OK

等待(*)

等待(*) 等待(*) 等待(*) OK 等待(*) 等待(*) OK 等待(*)
等待(*):如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据
注:黄色代表和可重复读不同的地方

从上面的表可以看出,MySQL在实现可串行化时,MVCC施了严格的封锁严格意义上的可串行化,代价是发性的极大损失

3. 可重复读存在的问题
可重复读隔离级别下,当发生更新等待后,如果先行事务提交更新,MySQL没有像其他支持MVCC的数据库(Oracle,SQL Server,PostgreSQL)那样报错。而是读到了更新后的数据。这就可能导致幻读,甚至不可重复读。根据可重复读的定义,幻读是允许的,但出现不可重复读就是一个严重的Bug了。
下面用一个例子来说明这个问题。

表定义及初始数据:
create table tb2(id int primary key,name varchar(30),name2 varchar(30));
insert into tb2 values(1,'a','a');

No 事务1 事务2 备注
1 select * from tb2 where id=1;
   id      name    name2
1       1       a       a


2
update tb2 set name2='b' where id=1;
1 Rows updated!

3 select * from tb2 where id=1;
   id      name    name2
1       1       a       a

很好:没有出现脏读
4
commit
5 select * from tb2 where id=1;
   id      name    name2
1       1       a       a

很好:没有出现不可重复读
6 update tb2 set name='a1' where id=1;
1 Rows updated!


7 select * from tb2 where id=1;
   id      name    name2
1       1       a1      b

糟糕:name2的值怎么跟以前不一样了。(即出现了不可重复读)
8 commit



4. 总结
综合MySQL(Innodb) 的4种隔离级别的实测结果,总结如下:
读未提交:不推荐。并发性(读写互不阻塞)上对读已提交没有优势,而且还会出现脏读。
读已提交:基于MVCC实现了读写互不阻塞。并发性很好。
可重复读:并发性同样很好,并且有更好的数据一致性
但在执行过更新后,可能出现不可重复读,使用的时候要小心。
可串行化:并发事务间极容易出现阻塞,请确信你真的需要这么严格的隔离保护。




阅读(3329) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~