mysql 锁的理解

分类1:

表锁:锁住全表,myisam仅提供表锁,但不提供事务。

行锁:在加锁过程中如果走了索引,则锁住通过索引查询到的记录。如果没有走索引,则可能锁住所有记录,变成了表锁了。

注意:行锁仅在事务中才有效,不在事务行锁无效,即使锁住了记录,其它程序也可以操作记录并能正常提交,结果如下所示。

但myisam的表锁,请大家自行研究,没有试验过。

 

分类2:

共享锁(读锁):事务A对记录加了共享锁,则其它事务可以再加共享锁,但无法加排它锁。

排他锁(写锁):select XXX for update增加排它锁,在加排他锁的时候,在未提交的时候,允许其他的事务做查询操作。但不允许其他事务对排他锁锁住的记录做修改操作,但不在排它锁锁住的记录,是允许做修改操作的。实例如下

1.事务A 新增排它锁

 1.1. 事务B不允许增加排它锁,直至超时报错

1.2 事务B能够操作事务A中未锁定的记录,如事务B给

1.3 事务A可以对已经排他锁的记录继续加锁

1.4 事务A锁住记录id = 1,事务B能够对记录id =2的事务A未锁住的记录做操作和加排它锁

1.5 同理事务A可以对记录ID = 1进行操作,事务B可以对记录id = 2进行操作

 

1.6 如果此时事务A想对id = 2进行操作,事务B相对id = 1的记录进行操作,这样就进入了事务A等待事务B解锁记录id = 2,事务B在等待事务A解锁id = 1的记录,则进入了死循环。

可以看出,事务B在mysql中检测到了死循环Deadlock,mysql重启了事务,这个时候事务B其实已经不存在,事务A就可以操作id =2 的记录了。可以看出事务A成功的操作了id = 2的原有事务B锁住的记录。

由于事务A已经提交了,从事务的集合中去除了,而事务B也不见了,则此时没有事务了,结果如下

 

重新开启了事务B,则可以看到事务集合中事务的个数为1

 

重新开启事务A,事务A可以查看事务B锁住的id=2的记录,但无法修改id=2的记录或给id=2的记录加锁,表现如下

 

由上图所示,事务A依旧可以查看事务B锁住的记录,但无法修改事务B锁住的记录和对事务B锁住的记录加锁。

注:除非修改mysql.ini中的配置,如innodb_lock_wait_timeout,否则在程序或者mysql终端设置的参数,仅对本进程有效。而且进程使用CTRL+C终止,或者程序挂了,但锁并未解除,如下所示

 

总结下排他锁:

1. mysql如果没有启用事务,则任何一个操作都是事务。

2. mysql中事务A加了排他锁,锁住了相关的记录,则事务B无法对事务A锁住的记录加锁,也无法修改事务B操作的记录。事务A会一直等待事务B提交后再修改。如果事务A和事务B互相锁住对方的记录,则形成了循环死锁,mysql会自动解除掉其中一个死锁,但在很复杂的死锁中,可能mysql也无法解开,就会影响mysql的操作性能。

3. 事务中如果事务A给某条记录加了排他锁,而由于某种原因,事务A一直没有提交,则会一直锁住相关的记录,别的事务无法处理被锁住的纪录,影响了后续的操作。

4. 一般不建议在大并发下使用排它锁,可以使用乐观锁或者redis队列替代排它锁。

分类3:

乐观锁(利用UPDATE的序列化执行和UPDATE的WHERE始终查询到最新一次事务提交的修改数据的特性):

    将数据记录中新增一个版本字段,每次修改记录的时候先获取版本的值,然后再更新操作中查询记录的版本是否和上次查询到的版本相同,如果相同则可以修改,并插入数据表记录。否则认为在该事务的查询和更新操作之间,已经有别的事务修改了此条记录的值,并已经成功提交了事务,造成本次查询的版本已经和上次查询的版本不一致,则不会修改,返回修改的记录为0 ,通过此方法阻止了并发。

悲观锁(排他锁):即写锁,排他锁。

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值