当前位置:   article > 正文

一篇文章搞懂Mysql中的行锁、表锁、悲观锁、乐观锁、活锁、死锁、封锁协议、MVCC锁_悲观锁 和 行锁

悲观锁 和 行锁

一、Mysql中的行锁和表锁

这里主要参考:https://mp.weixin.qq.com/s/Wq8-fdH_WR-2lvf-Lut5Yw

1.1 锁的粒度

MySQL 源码中定义了两种锁的粒度,分别是表锁和行锁。

/** Lock types */
#define LOCK_TABLE 16  /*!< table lock */
#define LOCK_REC 32    /*!< record lock */
  • 1
  • 2
  • 3

表锁是指对一整张表加锁,一般是 DDL 处理时使用;而行锁则是锁定某一行或者某几行,或者行与行之间的间隙。

表锁由 MySQL Server 实现,行锁则是存储引擎实现,不同的引擎实现的不同。在 MySQL 的常用引擎中 InnoDB 支持行锁,而 MyISAM 则只能使用 MySQL Server 提供的表锁。

(1)表锁

表锁由 MySQL Server 控制,优点是开销小、加锁快,不会产生死锁,缺点是加锁粒度大,发生锁冲突的概率大,并发度比较低。

一般 DDL (Data Define Languge,如create、drop、alter)语句会自动加表锁,也可以手动指定。表锁分为读锁和写锁。

//加读锁
lock table products read;
//加写锁
lock table products write;
  • 1
  • 2
  • 3
  • 4

当对表加了读锁,则会话可以读取但不能写入当前被加锁的表,并且只能访问加锁的表(直到最后通过 unlock tables 释放所有表锁),其它会话仍然可以对加锁的表进行读取但不能写入

当对表加了写锁,则会话可以读取或写入被加锁的表,并且只能操作加锁的表(直到最后通过 unlock tables 释放所有表锁),其它会话不能对加锁的表进行读取或写入

(2)行锁

行锁由存储引擎实现,InnoDB 支持,而 MyISAM 不支持。行锁的优点是锁粒度,小发生锁冲突概率小,并发度高,缺点是开销大、加锁慢,并且可能产生死锁。

InnoDB 行锁是通过索引项加锁来实现的,只有通过索引条件检索数据,才能锁住指定的索引记录,否则将使用行锁锁住全部数据(有文章称会退化为表锁,是错误的理解)。

表级锁适合查询多、更新少的场景,行级锁适合按索引更新频率高的场景InnoDB 默认使用行级锁

(3)页面锁

页面是Mysql最小的逻辑单位,InnoDB每个页面为16K,读取一个页面时,需要对页面加S锁,更新一个页面时,需要对页面加上X锁。任何情况下,操作一个页面,都会对页面加锁,页面锁加上之后,页面内存储的索引记录才不会被并发修改。

页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般

1.2 锁的模式

MySQL 源码中定义了多种锁的模式,如下:

/* Basic lock modes */
enum lock_mode {
  LOCK_IS = 0,          /* intention shared */
  LOCK_IX,              /* intention exclusive */
  LOCK_S,               /* shared */
  LOCK_X,               /* exclusive */
  LOCK_AUTO_INC,        /* locks the auto-inc counter of a table in an exclusive mode */
 ...
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

行锁的模式:共享锁和排它锁。

共享锁和排它锁都是行级锁。

Shared Lock (S 锁),共享锁,也称为读锁。当事务对行加共享锁后,允许其它事务对相同行加共享锁,但不允许加排它锁。如果加排他锁可以使用select ...for update语句。

Exclusive Lock (X 锁),排它锁,也称为写锁。当事务对行加排它锁后,不允许其它事务

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/998352
推荐阅读
相关标签
  

闽ICP备14008679号