MySql锁的分类和死锁的产生和预防

MySql中锁的分类

性能:

  • 悲观锁:对于数据库中的数据读写持悲观态度,实现需要依赖数据库的锁机制,读写都加锁
  • 乐观锁:对于数据库中的数据读写持乐观态度,通过MVCC版本对比来实现的

操作类型:

  • 读锁:都是悲观锁,又称为共享锁或S锁,同一份数据可以加多个读锁互不影响
  • 写锁:都是悲观锁,又称为排他锁或X锁,当前写锁未释放,不能加其他读写锁

数据粒度:

  • 表锁:也称为表级锁,整个表上的数据加锁和释放锁。典型的特点是开销比较小,加锁速度快,一般不会出现死锁,锁定的力度比较大,发生锁冲突的概率最高,并发度最低。
    MySql中有两种表级锁:表共享锁和表独占写锁。
    mysql通过该命令手动加锁
lock table 表名称 read(write),表名称2 read(write)

mysql通过该命令释放锁

unlock tables;
  • 行锁:也称为行级锁,就是在数据行上对数据进行加锁和释放锁,典型特点是开销比较大,加锁速度慢,可能会出现死锁,锁定的力度最小,发生锁冲突的概率最小,并发度最高。
    在Innodb存储引擎中,有两种类型的表锁:共享锁和排他锁。共享锁只允许其他事务读,不允许其他事务写。排他锁只允许当前事务进行增删改查操作,不允许其他事务进行任何操作。
    注意:
    1.行锁要加在索引上,如果对费索引的字段设置条件进行更新,行锁可能会变为表锁
    2.Innodb的行锁是针对索引加锁,不是针对记录加锁,并且加锁的索引不能失效,否则行锁可能会变为表锁
    3.锁定某一行时,可以使用lock in share mode指定共享锁,使用for update 指定排他锁
  • 页面锁:页级锁,在页面级别对数据进行加锁和释放锁对数据的加锁开销和锁定粒度大小介于表锁和行锁之间,并发度一般可能发生死锁

更细粒度:

  • 间隙锁:在mysql使用范围查询的时候,如果请求的是共享锁或者排他锁,innodb会给符合条件的已有数据的索引项加锁。如果兼职在范围区间,但是这个范围不存在记录,则认为此时出现了间隙,innodb会给这个间隙加间隙锁。
    mysql默认的隔离级别是可重复读,该级别下会存在幻读问题,间隙锁在某种程度可以解决幻读。间隙锁只有在可重复读的隔离级别才会生效
  • 临键锁:行锁和间隙锁的组合

死锁的产生和预防

死锁的必要条件

互斥条件:一段时间内,计算机中的某个资源只能被一个进程占用,其他进程请求会等待
不可剥夺条件:某个进程在资源使用完毕之前,不能被其他进程强行夺走,只能等待持有资源的进程主动释放
请求与保持条件:占有一个资源还请求其他的,并且不会释放自己的
循环等待条件:进程之间相互等待

处理死锁的方法

预防死锁:破坏产生死锁的条件
避免死锁:资源分配的时候防止系统进入不安全状态
检测死锁:允许产生死锁,但是能够检测死锁的状态,并采取措施清除死锁
解除死锁:出现死锁之后,使用适当的策略和方法让进程从死锁中解脱出来

MySQL中的死锁问题

mysql默认的存储引擎是innodb,使用的是行级锁,会产生死锁,innodb使用了等待图的方法自动检测死锁,如果发现死锁,就会自动回滚事务。

避免死锁

1.尽量让数据表检索走索引完成,避免无效索引导致行锁升级为表锁。
2.合理设计索引,减小锁的范围
3.减少查询条件的范围,尽量避免间隙锁或缩小间隙锁范围
4.尽量控制事务大小,减少一次事务锁定的资源数量,缩短锁定资源时间
5.SQL语句涉及事务加锁操作,尽量放在整个事务的最后执行
6.尽可能使用低级别的事务隔离机制

猜你喜欢

转载自blog.csdn.net/qq_37200262/article/details/125350660