一:CREATE TABLE `t` (
`id` int(11) NOT NULL,
`c` int(11) DEFAULT NULL,
`d` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `c` (`c`)
) ENGINE=InnoDB;
insert into t values(0,0,0),(5,5,5),
(10,10,10),(15,15,15),(20,20,20),(25,25,25);
begin;
select * from t where d=5 for update;
commit;
这条语句会命中d=5这一行,对应主键是id =5 ,这一行会加一个写锁。 由于d 上没有索引,这条语句查询的时候会做全表扫描。但是 不满足条件的5行记录上会不会加锁呢?
二:幻读是什么:
查询语句用的是当前读,并且加上了些锁。Q3读到id = 1 这一行的现象称为幻读。
1.在可重复读隔离级别下,普通查询是快照读,是不会看到别的事务插入的数据,幻读在当前读下才会出现。
2.sessionb 的修改结果被sessiona读到,不能称为幻读,幻读指的是行插入的行
幻读有什么问题:
1.语义上的。
sessonA是要给d=5的加锁。但是sessionB ,sessionC 都可以执行成功。sessionA只是给id = 5 加了锁。
2 。破坏了数据一致性
这个一致性,不止是数据库内部数据状态在此刻的一致性,还包含了数据和日志在逻辑上的一致性。
update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/
insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/
update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/
insert into t values(1,1,5); /*(1,1,5)*/
update t set c=5 where id=1; /*(1,5,5)*/
update t set d=100 where d=5;/* 所有 d=5 的行,d 改成 100*/
update t set d=5 where id=0; /*(0,0,5)*/
update t set c=5 where id=0; /*(0,5,5)*/
上边把表的所有数据都加了锁,但是还是插入了数据 。
如何解决幻读?
新插入的语句是更新的记录之间的间隙。为了解决这个问题,引入了间隙锁。
产生 了七个间隙 。
select * from t where d= 5 for update;,不止给6个记录加上了行锁。同时还加了7个间隙锁。这样就确保无法插入新的记录。
跟间隙锁存在冲突关系的是往这个间隙中插入一个记录,这个操作。间隙锁之间都不存在冲突关系。
这俩条语句都加了 (5,10)这个间隙锁,但是不冲突,不会吧sessionB阻塞住。
select * from t for update 是把整个表的所有记录锁起来。就形成了7个next-key-lock.
但是也会出现问题。就是会发生死锁;
可能会引出并发读。
原文地址:https://www.cnblogs.com/hanguocai/p/10195045.html