数据库高级-锁

1、没有索引的情况下:

情况一:两个事务,A、B
第一步:A去更新某一行的时候,若果where后面的字段是非索引的,会把表里每一行加上u锁(更新锁)
第二步:将那一行的u锁变为x锁(排它锁),若未提交,x锁继续保留,
第三步:把其他的u锁释放掉

如果A事务未提交,B事务去更新另一行,则需要获得到A事务更新的那一行的u型锁,但是这一行已经被A事务用排它锁锁住了,所以需要等待X锁的释放。

情况2:两个事务,A、B

A:对表进行扫描依此对每行记录下U锁,若满足条件则转换为X锁更新,若不满足条件则释放U锁。更新完成后,若未提交则X锁继续保留。

B:对表进行扫描依此对每行记录下U锁,因为需要update的条件在此时前被发现加上X锁,但是扫描到查询1锁添加的X锁后无法添加U锁导致需要等待A事务完成后才能继续提交。这时A事务的第二个update语句开始运行,更新U锁时,发现B的X,要等待B的X锁释放同时达成死锁条件。

2、有索引的情况

mysql的事务支持与存储引擎有关,MyISAM不支持事务,INNODB支持事务,更新时采用的是行级锁。这里采用的是INNODB做存储引擎,意味着会将update语句做为一个事务来处理。
行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。

事务1用到的 SQL 语句:
UPDATE authorized_user SET status = 1 WHERE username = ‘wcy’
事务1获取的锁:X lock on (669,13359,1176) index_username
事务1等待的锁:X lock on (669,937,136) PRIMARY

事务2用到的 SQL 语句:
UPDATE authorized_user SET username = ‘wcy100’ WHERE id = 1
事务2获取的锁:X lock on (669,937,136) PRIMARY
事务2等待的锁:X lock on (669,13359,1176) index_username

事务1的 update 语句正常的执行步骤如下:
1.由于用到了非聚簇索引,首先需要获取 index_username 上的行级锁。
2.紧接着根据主键进行更新,所以需要获取 PRIMAEY 上的行级锁。
3.更新完毕后,提交,并释放所有锁。

但是,如果在步骤1和2之间突然插入事务2的这条 SQL 语句:
UPDATE authorized_user SET username = ‘wcy100’ WHERE id = 1, 这条语句会先锁住聚簇索引,然后由于其更新的字段 username 有非聚簇索引,所以这条语句需要锁住 index_username。这条语句更新的字段 username 上有索引,在更新字段值之后需要更新索引,因此语句要在索引 index_username 上加锁。

3、
name age
aa 1
bb 2

事务A:
    UPDATE `user` SET `age`=1 WHERE `name`='aa';
事务B:
    UPDATE `user` SET `name`='bb' WHERE `age`=2 ;

如果name和age都有索引,则没有冲突
如果name和age有一个不是索引,则需要等待

猜你喜欢

转载自blog.csdn.net/u014229652/article/details/81711122