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

posted @ 2019-08-23 21:17  数据是宝  阅读(769)  评论(0编辑  收藏  举报