ITPUB论坛-中国专业的IT技术社区

 找回密码
 注册
查看: 5037|回复: 14

[原创] 一个mysql 范围锁的问题,请高手解惑!

[复制链接]
论坛徽章:
1
优秀写手
日期:2014-05-08 05:59:47
跳转到指定楼层
1#
发表于 2014-2-27 11:16 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 liushuiwuqing4 于 2014-2-27 11:21 编辑

1.创建了一个t表
mysql> create table z (a int  primary key,b int , key(b));

2.插入数据后:
mysql> select * from z;
+----+------+
| a  | b    |
+----+------+
|  1 |    1 |
|  3 |    1 |
|  5 |    3 |
|  7 |    6 |
| 10 |    8 |
+----+------+

3.一个session1执行  begin ; 然后 select * from z where b=3 for update;  这时候session1的事务会对a=5上record lock ,并且对 b属于(1,3)(3.6)上范围锁。(当然不是自动提交的,我设置的autocommit=0)

4.另一个session2 (也是autocommit=0)执行 begin; 然后  insert into z select 8,6; 是可以的,回滚后,我执行 mysql> insert into z select 6,6;  却不行,就会被 阻塞住。  
按理说a列是cluster index 列,a=8 和a=6本身没有什么区别的,因为针对聚集索引的锁就是record lock嘛。 可是(6,6)为什么不行呢?望热心人解惑,在线等着,谢谢。


ps:mysql 版本 5.5.36

论坛徽章:
1
优秀写手
日期:2014-05-08 05:59:47
2#
 楼主| 发表于 2014-2-27 11:34 | 只看该作者
我即使第二个session 执行
mysql> use pointintime;
Database changed
mysql> begin;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into z select 6,6;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
它依然还是无法插入的,感觉就是这个6,6 数据是不能插入进去的。

使用道具 举报

回复
论坛徽章:
4
奔驰
日期:2013-08-01 10:31:12ITPUB社区12周年站庆徽章
日期:2013-08-13 16:52:38奥迪
日期:2013-09-12 10:42:18奔驰
日期:2013-12-27 20:52:52
3#
发表于 2014-2-28 10:13 | 只看该作者
liushuiwuqing4 发表于 2014-2-27 11:34
我即使第二个session 执行
mysql> use pointintime;
Database changed

注意下:对 b属于(1,3)(3.6)上GAP锁,你插入的6,6是在这个gap锁范围内的,这样就会报错;而你插入的8,6则是在那个gap锁范围之外的,所以,不存在问题~~

使用道具 举报

回复
论坛徽章:
56
马上加薪
日期:2014-12-22 13:11:12复活蛋
日期:2011-08-31 14:55:20ITPUB9周年纪念徽章
日期:2010-10-08 09:32:252010世博会纪念徽章
日期:2010-09-07 08:52:012010年世界杯参赛球队:瑞士
日期:2010-06-24 09:16:222010年世界杯参赛球队:德国
日期:2010-04-27 09:40:272010年世界杯参赛球队:韩国
日期:2010-04-23 23:34:412010新春纪念徽章
日期:2010-03-01 11:06:222010新春纪念徽章
日期:2010-01-04 08:33:08参与WIN7挑战赛纪念
日期:2009-11-06 10:44:24
4#
发表于 2014-2-28 18:02 | 只看该作者
1.select * from z where b=3 for update
会对a=5上record lock ,并且对 b上范围锁next key lock,锁定范围为(1,6)
2.insert into z select 8,6成功而insert into z select 6,6失败的原因是
对于插入到列b的值为列b的锁定范围右边界时(这里b=6),则插入到列a的值必须大于右边界对应的a列的值的最小值(这里a的最小值为7),否则会被阻塞。

使用道具 举报

回复
论坛徽章:
2
2014年新春福章
日期:2014-02-18 16:48:49马上加薪
日期:2014-02-18 16:48:49
5#
发表于 2014-2-28 22:40 | 只看该作者
很简单,mysql实现x锁是通过主键实现的,而s锁是通过辅助索引实现的

使用道具 举报

回复
论坛徽章:
0
6#
发表于 2014-3-1 13:09 | 只看该作者
我也有一个类似的问题,
但是感觉更加迷惑,
大家能帮我看看吗
/thread-1847072-1-2.html

使用道具 举报

回复
论坛徽章:
1
优秀写手
日期:2014-05-08 05:59:47
7#
 楼主| 发表于 2014-4-30 11:16 | 只看该作者
waityou81 发表于 2014-2-28 18:02
1.select * from z where b=3 for update
会对a=5上record lock ,并且对 b上范围锁next key lock,锁定范围 ...

您的评论还是最切中我想要说的,您说的红色字体部分我只能知道是这个结果或者说是这个规律,因为我的测试结果也说明了这个原因,可是不能理解真正的原因。

当然这个在平时可能很少遇到,只是我比较纠结这个事情而已。

使用道具 举报

回复
论坛徽章:
1
优秀写手
日期:2014-05-08 05:59:47
8#
 楼主| 发表于 2014-4-30 11:18 | 只看该作者
冷月汉宫秋 发表于 2014-2-28 10:13
注意下:对 b属于(1,3)(3.6)上GAP锁,你插入的6,6是在这个gap锁范围内的,这样就会报错;而你插入的8 ...

你的解释也就是我的问题,为什么 6.6在gap之内,而8.6在gap之外呢?

使用道具 举报

回复
论坛徽章:
8
2009日食纪念
日期:2009-07-22 09:30:002010年世界杯参赛球队:巴拉圭
日期:2010-08-31 10:49:49ITPUB9周年纪念徽章
日期:2010-10-08 09:31:222010广州亚运会纪念徽章:射箭
日期:2010-11-11 10:15:282010广州亚运会纪念徽章:羽毛球
日期:2010-11-11 10:15:332010广州亚运会纪念徽章:马术
日期:2010-11-11 10:15:40蜘蛛蛋
日期:2011-12-27 15:41:052012新春纪念徽章
日期:2012-01-04 11:54:26
9#
发表于 2014-5-5 11:16 | 只看该作者
这篇文章对楼主问问题解释的很清楚,希望对楼主有用:
http://hedengcheng.com/?p=771

使用道具 举报

回复
论坛徽章:
5
复活蛋
日期:2012-11-02 16:27:37灰彻蛋
日期:2013-01-27 17:08:112013年新春福章
日期:2013-02-25 14:51:24复活蛋
日期:2013-05-27 15:29:10优秀写手
日期:2014-07-01 06:00:12
10#
发表于 2014-5-6 00:34 | 只看该作者
很简单,8,6 是在7,6的后面,而6,6是在7,6的前面,也就是说8,6在gap锁的外面,6,6正好在gap锁的范围中

使用道具 举报

回复

您需要登录后才可以回帖 登录 | 注册

本版积分规则

TOP技术积分榜 社区积分榜 徽章 电子杂志 团队 统计 虎吧 老博客 知识索引树 读书频道 积分竞拍 文本模式 帮助
  ITPUB首页 | ITPUB论坛 | 数据库技术 | 企业信息化 | 开发技术 | 微软技术 | 软件工程与项目管理 | IBM技术园地 | 行业纵向讨论 | IT招聘 | IT文档 | IT博客
  ChinaUnix | ChinaUnix博客 | ChinaUnix论坛 | SAP ERP系统
CopyRight 1999-2011 itpub.net All Right Reserved. 北京盛拓优讯信息技术有限公司版权所有 联系我们 网站律师 隐私政策 知识产权声明
京ICP备16024965号 北京市公安局海淀分局网监中心备案编号:11010802021510 广播电视节目制作经营许可证:编号(京)字第1149号
  
快速回复 返回顶部 返回列表
http://www.vxiaotou.com