• mysql中的锁


      关键词:行锁、表锁、乐观锁、悲观锁、gap锁、next-key

    一、行锁与表锁:

    1、表锁: 

    锁定粒度是表
    (1)意向共享锁(IS):事务如果想要读某一个数据行,那么必须取得该表的IS锁。
    (2)意向排他锁(IX):事务如果想要对某一个数据行进行更新操作,那么必须先取得该表的IX锁。
    (3)加锁方式:
    • 意向共享锁(IS):LOCK table tableName read;
    • 意向排他锁(IX):LOCK table tableName write;

    2、行锁(记录锁)--共享锁和排他锁: 

    锁定粒度是数据行
    (1)共享锁(读锁、S锁):事务在读某一个数据行时,如果给当前数据行加上S锁,那么此时只允许其他事务读取当前数据行,而禁止其他事务对当前数据行进行写操作。
    (2)排他锁(写锁、X锁):事务在对某一个数据行进行更新操作时,如果给当前数据行加上X锁,那么会禁止其他事务对相同的数据行进行读或者写操作。
    (3)InnoDB引擎下的行锁分析:
      ①对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及的数据集加排他锁(X);
      ②对于普通SELECT语句,InnoDB不会加任何锁,事务可以通过以下语句显示给记录集加共享锁或排他锁。
      • 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE。
      • 排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE。  (悲观锁的实现方式)
      ③InnoDB行锁是通过给索引上的索引项加锁来实现的,因此InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁(主键字段默认是有索引的)。
    (4)MyISAM引擎下的行锁分析:MyISAM在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等)前,会自动给涉及的表加写锁。

    3、总结:

    (1)应用中我们只会使用到共享锁和排他锁,意向锁是mysql内部使用的,不需要用户干预。
    (2)InnoDB&Myisam引擎的锁机制:InnoDB支持事务,支持行锁和表锁用的比较多;Myisam不支持事务,只支持表锁。

    二、乐观锁和悲观锁:

    1、悲观锁:

    (1)定义:
      正如其名,悲观。实际上就是说在操作数据的时候,总是还怕此时别的事务可能也会修改数据,所以,一旦操作数据,那么就对数据加锁,一旦操作数据,就对当前的数据加锁,防止其他事务操作这个数据。
    (2)实现:
      ①select * from table where ... for update    (写锁)
      ②select * from table where ... lock in share mode (读锁) 

    2、乐观锁:

    (1)定义:
      正如其名,乐观。实际上就是说在操作数据的时候,不怕别的事务也在修改,总是觉得没事的,不会这么巧的。所以在刚开始操作数据的时候并没有对数据进行加锁。而是等到提交事务时,再对数据做一个检查,判断此时数据是否修改了。如果数据被修改了,那么此时返回错误信息,让用户自己再选择怎样做,一般是回滚事务。
    (2)实现:
      在修改数据的时候,首先记录下数据的原始值。然后在修改的时候再判断是否这个数据发生改变了。如果改变了说明出错了。此时用户再进行相对应的操作。否则说明没有错误,继续执行。

    3、应用:

    (1)改某字段的值时,可以使用乐观锁或者悲观锁。
    eg:更新账户金额应该的sql语句写成这样子: update order_info set o.money=money-10  
    而不应该先查询money计算完成后再进行更新
       money = money - 10 ; # 语句1
       update order_info set o.money = money  # 语句2
    注意:如果在语句1设置money的值,那么在mysql准备执行语句2的时候,可能money的值已经被其它事务修改了。如果这样子就会导致数据出错。 

    三、间隙锁(gap锁):

    1、定义:

      在RR级别下,检索某个内容时,会对其间隙加间隙锁。本质上等同于S锁。

    2、分析:

      比如此时表中有记录(id=6,number=5)与(id=8,number=5),那么此时(id=6,number=5)与(id=8,number=5)之间就是存在间隙的,比如可以插入记录(id=7,number=5)。所以此时如果开启了间隙锁的机制,那么会对(id=6,number=5)与(id=8,number=5)之间的间隙加锁,禁止在间隙添加记录。

    3、核心作用:

    在mysql的innodb引擎的RR级别下使用间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的。

      ①防止间隙内有新数据被插入;
      ②防止已存在的数据,更新成间隙内的数据(例如防止numer=3的记录通过update变成number=5)。

    4、innodb自动使用间隙锁的条件:

      ①必须在RR级别下
      ②当前读而且检索条件必须有索引(eg:主键)
      详见:

    四、 next-key锁:

    1、next-key锁其实包含了行锁和间隙锁,即锁定一个范围,并且锁定记录本身。
    2、分析:
      如下数据表与sql语句:select * from news where number=4 for update ;
     
      此时,next-key锁利用间隙锁+行锁,锁定的方式是:为区间(2,4),(4,5)加间隙锁,同时对number=4的记录加行锁。

    五、死锁

     
     

    参考资料:

    https://www.cnblogs.com/protected/p/6526857.html

    https://www.cnblogs.com/crazylqy/p/7821481.html

    https://blog.csdn.net/xts5701046/article/details/81395958

    https://blog.csdn.net/lostvip/article/details/82818996

  • 相关阅读:
    教你如何让数据库支持emoji表情符存储
    PHP下载远程图片的3个方法
    CentOS7安装使用MySQL
    记录几个项目管理软件
    C++和C在linux下 和在windows下有什么区别?
    nginx配置location总结及rewrite规则写法
    A记录和CNAME记录的区别
    Nginx配置https的wordpress站点,wp-content目录下资源404解决方案
    清除chrome浏览器HSTS缓存
    面向对象基础----封装数据库操作类
  • 原文地址:https://www.cnblogs.com/axing-articles/p/11415058.html
Copyright © 2020-2023  润新知