mysql的innodb无索引情况下行锁问题

[复制链接]
查看11 | 回复9 | 2019-1-25 11:35:05 | 显示全部楼层 |阅读模式
我在阅读《深入浅出MySQL++数据库开发、优化与管理维护 第二版》时,在第20章的20.3.4 InnoDB行锁实现方式时有个疑问,感觉内容前后矛盾,请大家解惑下,不胜感激!!!
原文:
InnoDB行锁是通过给索引上的索引项加锁来实现的,如果没有索引,InnoDB将通过隐藏的聚簇索引来对记录加锁。InnoDB行锁分为3中情形。
1、Record lock:对索引项加锁
2、Gap lock:对索引项之间的“间隙”、第一条记录前的“间隙”或最后一条记录后的“间隙”加锁
3、Next-key lock:前两种的组合,对记录及其前面的间隙加锁
InnoDB这种行锁实现特点意味着:如果不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,实际效果跟表锁一样!
我感觉矛盾的地方:
原文开头说没有索引他会通过隐藏的聚簇索引来对记录加锁,
但是后面又说,如果不通过索引条件检索数据,那么innodb的行锁将变成表锁,
在这问题来了,不是有隐藏索引么,也说了能通过隐藏的聚簇索引对记录加锁,
如果没有索引,直接简单的一个select * from tab where id=1语句,他不能通过隐藏索引对这条id=1的记录加行锁么?
书中的测试结果显示,确实是不行的,没有显式索引就是表锁。
我对这句话“InnoDB将通过隐藏的聚簇索引来对记录加锁”的理解有两个:
1、通过隐藏的聚簇索引来对表中的所有记录加行锁,来实现表锁;这代价也太大了,完全没必要啊
2、我的select * from tab where id=1语句没有用上这个隐藏的聚簇索引,所以成了表锁,那么,怎样才能利用上这个隐藏的聚簇索引呢,使没有显式索引的语句也能加行锁。
************************************************
请大家给我解惑啊,非常感谢


回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
顶一下。路过的童鞋也帮忙顶顶
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层





回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
innodb 的行锁是加在索引上的, 如果没有主键 那么在行头记录ROWID如下:
000001cc6426 ROWID
0000002d0272 transaction id
d300000d120110 roll pointer
80000002 数据2,这里8出现在第15位,可能为符号位
67616f70656e67 数据'gaopeng'的ascII值
如果没有索引的情况对任何条件的DML都是表级别的锁, 但是UPDATE有个例外semi-consistent read
主要原因在于如果不锁定不能保证隔离级别。而你所说的select是不存在锁的,这是UNDO来保证的。
除非你for update,
关于next-key-lock 原理参考下我写的:
RR模式下NEXT-KEY LOCK范围到底有多大
http://blog.itpub.net/7728585/viewspace-2126305/
当然这些是在RR模式下在RC模式下不存在next-key lock,只有行锁。
其实如果了解ORACLE 就会觉得MYSQL INNODB的锁基于索引
有点恶心,但是不然他实际上是为了RR模式隔离级别而生的。
此外加锁的过程是 表级别 一把meta data lock,索引行上回上一把ROW LOCK 或者NEXT KEY LOCK
其次主键上(也就是表本身)也会上一把ROW LOCK 或者NEXT KEY LOCK

回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
gaopengtttt 发表于 2017-2-16 16:11
innodb 的行锁是加在索引上的, 如果没有主键 那么在行头记录ROWID如下:
000001cc6426 ROWID
0000002d ...

大神,我其实想问的能否通过这个000001cc6426 ROWID来进行加锁,在没有显式创建索引的情况下也能实现行级锁
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLE的ROWID那样可引用,是隐含的)。
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
在默认隔离级别下,MySQL不会对你说的那个select加锁
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
lujinke 发表于 2017-3-8 15:46
在默认隔离级别下,MySQL不会对你说的那个select加锁

rr级别,事务情况下会吧,begin;然后select
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
running_life 发表于 2017-3-9 15:27
rr级别,事务情况下会吧,begin;然后select

不会,RR级别下这种读读的是快照
回复

使用道具 举报

千问 | 2019-1-25 11:35:05 | 显示全部楼层
lujinke 发表于 2017-3-10 17:13
不会,RR级别下这种读读的是快照

快照读感觉他也加了gap锁呢,我如果查询为select * from t where id>10;我在另外session插入大于10的数据就卡主了
回复

使用道具 举报

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

本版积分规则

主题

0

回帖

4882万

积分

论坛元老

Rank: 8Rank: 8

积分
48824836
热门排行