赞
踩
这里主要参考:https://mp.weixin.qq.com/s/Wq8-fdH_WR-2lvf-Lut5Yw
MySQL 源码中定义了两种锁的粒度,分别是表锁和行锁。
/** Lock types */
#define LOCK_TABLE 16 /*!< table lock */
#define LOCK_REC 32 /*!< record lock */
表锁是指对一整张表加锁,一般是 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;
当对表加了读锁,则会话可以读取但不能写入当前被加锁的表,并且只能访问加锁的表(直到最后通过 unlock tables
释放所有表锁),其它会话仍然可以对加锁的表进行读取但不能写入。
当对表加了写锁,则会话可以读取或写入被加锁的表,并且只能操作加锁的表(直到最后通过 unlock tables
释放所有表锁),其它会话不能对加锁的表进行读取或写入。
(2)行锁
行锁由存储引擎实现,InnoDB 支持,而 MyISAM 不支持。行锁的优点是锁粒度,小发生锁冲突概率小,并发度高,缺点是开销大、加锁慢,并且可能产生死锁。
InnoDB 行锁是通过索引项加锁来实现的,只有通过索引条件检索数据,才能锁住指定的索引记录,否则将使用行锁锁住全部数据(有文章称会退化为表锁,是错误的理解)。
表级锁适合查询多、更新少的场景,行级锁适合按索引更新频率高的场景。InnoDB 默认使用行级锁。
(3)页面锁
页面是Mysql最小的逻辑单位,InnoDB每个页面为16K,读取一个页面时,需要对页面加S锁,更新一个页面时,需要对页面加上X锁。任何情况下,操作一个页面,都会对页面加锁,页面锁加上之后,页面内存储的索引记录才不会被并发修改。
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般
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 */
...
};
行锁的模式:共享锁和排它锁。
共享锁和排它锁都是行级锁。
Shared Lock (S 锁),共享锁,也称为读锁。当事务对行加共享锁后,允许其它事务对相同行加共享锁,但不允许加排它锁。如果加排他锁可以使用select ...for update
语句。
Exclusive Lock (X 锁),排它锁,也称为写锁。当事务对行加排它锁后,不允许其它事务
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。