MySQL - 锁

锁是计算机协调多个进程或线程并发访问某一资源的机制,在数据库中,除传统的计算资源(CPU、RAM、I/O)争用外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问性能的一个重要因素。

MySQL 中的锁可以分为以下三类:

  • 全局锁:锁定数据库中所有的表
  • 表级锁:每次操作锁住整张表
  • 行级锁:每次操作锁住表中对应的行数据

全局锁

全局锁就是对整个数据库实例加锁,加锁后整个实例处于只读状态,后续的 DML、DDL 语句都会无法执行,典型的使用场景就是做全库的备份,对所有表进行锁定,从而获取一致性视图,保证数据的完整性。

打开全局锁:

flush tables with read lock;

备份指定数据库,将 crm 数据库备份到当前命令行目录的 crm.sql 文件中,不是在 MySQL 的命令行中执行,可直接在 Windows 命令行执行即可。

mysqldump -u root -p crm > crm.sql

释放全局锁:

unlock tables;

在数据库中加全局锁,是一个比较重的操作,会存在以下问题:
1、如果在主库上备份,那么备份期间都不能执行更新操作,业务基本停滞。
2、如果在从库上备份,那么备份期间从库不能执行主库同步过来的二进制日志(binlog),导致主从延迟。

在 InnoDB 引擎中,我们可以在备份时添加参数--single-transaction来实现不加锁的一致性数据备份:

mysqldump --single-transaction -u root -p crm > crm.sql

表级锁

每次操作锁住整张表,锁定力度大,发生锁冲突的概率高,并发度最低。表级锁主要分一下几类:

  • 表锁
  • 元数据锁(meta data lock,MDL)
  • 意向锁
表锁

表锁可以分为两类:
1、表共享读锁(read lock),当前客户端对表加锁后和其它客户端只能读表中的数据,当前客户端对表的写操作直接报错,其它客户端的写操作会被阻塞,直到锁被释放后才继续执行。
2、表独占写锁(write lock),当前客户端对表加锁后其它客户端对表的读写操作将会被阻塞,直到锁被释放后才会继续执行

表锁的操作语法如下:

-- 加锁
lock tables 表名... read/write

-- 释放锁(直接关闭客户端连接也可以释放锁) 
unlock tables
元数据锁(MDL)

元数据可以简单的理解为表结构,元数据锁的加锁是系统自动控制的,无需显示指定,在访问一张表的时候会自动加上,该锁主要作用是维护表结构数据的一致性,在表上有没提交的事务时,对表结构的更新操作会处于阻塞状态。

MySQL5.5 开始引入了 MDL,在对一张表进行增删改查的时候,会自动加上 MDL 读锁(共享锁);在对表结构进行变更操作时,会加上 MDL 写锁(排它锁)。

意向锁

当对表中数据执行 DML 时会锁定行数据,此时如果其它客户端要对表加表锁,则需要检查表中每一行数据是否加锁了。为了避免在执行 DML 语句的时候,加的行锁与表锁冲突,在 InnoDB 中引入了意向锁,使得表锁不用检查每行数据是否加锁,减少了表锁的检查,提高了效率。

有了意向锁后,在执行 DML 时,先添加行数据锁,然后对整张表添加意向锁,其它客户端在添加表锁时先检查意向锁,如果意向锁和要添加的表锁是兼容的则添加成功,否则添加表锁的操作会被阻塞。

意向锁可以分为以下两类:
1、意向共享锁(IS),由语句 select ... lock in share mode 添加,与表锁中的表共享读锁兼容,与表独占写锁互斥。
2、意向排它锁(IX),由语句 insert、update、delete、select ... for update 添加,与表锁中的表共享读锁、表独占写锁都互斥。意向锁之间不会互斥。

行级锁

每次操作锁住对应的数据行,锁定粒度最小,发生冲突的概率最低,并发程度高,主要用在 InnoDB 存储引擎中。InnoDB 的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加锁的。

行级锁主要分为以下几类:
1、行锁(Record Lock):锁定单个行记录的锁,防止其他事务对其进行 update、delete,在
read committed、repeatable read 两种隔离级别下都支持。
2、间隙锁(Gap Lock):锁定索引记录左右的间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行 insert 产生幻读,在 repeatable read 隔离级别下支持。
3、临键锁(Next-Key Lock):行锁和间隙锁的组合,同时锁住数据和数据前面的间隙,在 repeatable read 隔离级别下支持。

行锁

在 InnoDB 中实现了两类行锁:
1、共享锁(s):允许获得共享锁的事务读取一行数据,允许其他事务获得相同数据集的共享锁,但阻止获得排它锁。共享锁和排它锁是互斥的。
2、排它锁(x):允许获取排它锁的事务更新一行数据,阻止其它事务获得相同数据集的共享锁和排它锁。排它锁和其它锁都是互斥的。

常见 SQL 操作对应的行锁类型:

SQL 行锁类型 说明
insert 排它锁 自动加锁
update 排它锁 自动加锁
delete 排它锁 自动加锁
select 不加锁
select ... lock in share mode 共享锁 需要手动在 select 后添加 lock in share mode
select ... for update 排它锁 需要手动在 select 后添加 for update

默认情况下,InnoDB 在 repeatable read 事务隔离级别下运行,并使用临键锁进行搜索和索引扫描来防止幻读。
1、针对唯一索引进行检索时,对已存在的记录进行等值匹配时, 临键锁会自动优化为行锁。
2、InnoDB 的行锁是针对索引加的锁,如果不通过索引字段检索数据,那么 InnoDB 会将表中的所有记录加锁,此时会升级为表锁,影响效率。

可以通过以下 SQL 查看意向锁以及行锁的加锁情况:

select object_schema, object_name, index_name, lock_type, lock_mode, lock_data from performance_schema.data_locks;
间隙锁、临键锁

间隙锁唯一的目是防止其它事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁。

默认情况下,InnoDB 在 repeatable read 事务隔离级别下运行,并使用临键锁锁进行搜索和索引扫描来防止幻读。
1、索引上的等值查询(唯一索引),给不存在的记录加锁时,临键锁优化为间隙锁。
2、索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询条件时,临键锁退化为间隙锁。
3、索引上的范围查询(唯一索引),会访问到不满足条件的第一个值为止。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容