mysql原理(九) 锁,你更新一条记录真的不会造成死锁吗?

锁是数据库区别于文件系统的一个关键特性。锁机制用于管理共享资源的并发访问。InnoDB除了在表上面进行上锁之外,在其他层面也会进行上锁,如操作缓冲池当中的LRU列表,删除、添加和移动都需要有锁的介入。本文只讨论在InnoDB中的锁。

一、InnoDB存储引擎中的锁

1.1 锁的类型

1)共享锁(s lock):允许多个事务读一行数据。
2)排它锁(x lock):允许一个事务修改或删除数据。

锁的兼容锁的不兼容

X S
X 不兼容 不兼容
S 不兼容 兼容

例:
T1获取了行r的共享锁,T2仍然可以获取r的共享锁,这称为锁的兼容
如果此时T3想要获取r的排他锁,则需要等到T1和T2释放r的共享锁之后,这称为锁的不兼容

InnoBD允许行级锁和表级锁同时存在,为了支持在不同粒度上执行加锁操作,支持了额外的锁方式,称之为意向锁(Intention Lock)。InnoDB设计的意向锁比较简单,因为其支持行级锁,所以意向锁仅设计在表锁上。其主要目的是为了揭示下一行将要被请求的锁类型。
1)意向共享锁(IS Lock)想要获得一张表中某几行的共享锁。
2)意向排它锁(IX Lock)想要获得一张表中某几行的排它锁。

意向锁不会阻塞除全表扫描以外的请求。

在information_schema当中有以下三张表可以让我们分析锁的情况:INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS

INNODB_TRX
首先查看INNODB_TRX中的主要段含义:

字段名 说明
trx_id 唯一事务id
trx_state 事务状态
trx_started 事务开始时间
trx_requested_lock_id 等待事务的锁id,如trx_wait为lock_wait的时候;如果不是trx_wait,则是null
trx_wait_started 事务等待开始时间
trx_weight 权重,该值反映修改和锁住的行数。当发生死锁需要回滚时,会回滚该值最小的记录
trx_mysql_thread_id mysql中的线程id
trx_query 事务运行的sql语句
例子

INNODB_LOCKS
首先查看INNODB_LOCKS中的主要段含义:
|字段名|说明|
|lock_id|锁的id|
|lock_trx_id|事务的id|
|lock_mode|锁模式|
|lock_type|锁的类型,表锁和行锁|
|lock_table|要加锁的表|
|lock_index|锁住的索引|
|lock_space|锁对象的space id|
|lock_page|事务锁定页的数量。表锁该值为null|
|lock_rec|事务锁定记录的数量,表锁该值为null|
|lock_data|事务锁定记录的主键值,表锁该值为null|

例子

INNODB_LOCK_WAITS
首先查看INNODB_LOCK_WAITS中的主要段含义:

字段名 说明
requesting_trx_id 申请锁资源的事务id
requested_lock_id 申请锁的id
blocking_trx_id 阻塞的事务id
blocking_lock_id 阻塞锁的id
例子

1.2 一致性非锁定读

一致性非锁定读是指InnoDB通过多版本并发控制MVCC(Multi-Version Concurrency Control)来读取当前执行时间数据库中行的数据。

如果一行或多行数据正在进行update或者delete操作,这时候另外的事务去读取这些数据并不会等待其释放锁,可以直接进行读取。读取的是其快照数据。

之所以称之为一致性非锁定读,因为不需要等到行上面的X锁进行释放即可进行读取。如下图所示:

一致性非锁定读 (1).png

快照数据是指行之前版本的数据,通过undo log实现。

如上图所示,一个行的版本可能有多个,一般称之为多版本技术,由此带来的并发控制称之为多版本并发控制(MVCC)

在事务隔离级别read commited(oracle默认)和repeatable read(innoDB的默认隔离级别)中,使用非锁定一致性读,然而其对于快照读的定义却不相同。

隔离级别 读取版本
rc 读取最新版本数据
rr 读取最开始版本数据

下面看个例子:

时间 会话1 会话2
1 begin
2 select * from student where id = 1
3 begin
4 update student set id =3 where id = 1
5 select * from student where id = 1
6 commit
7 select * from student where id = 1
8 commit

如上表格所示:
在rr级别下,会话1读取到的结果分别是:1,1,1
在rc级别下,会话1读取到的结果分别是:1,1,empty

1.3 一致性锁定读

在某些特定情况下,用户需要显示的对数据库读取进行加锁操作以保证数据的一致性。InnoDB对select支持两种一致性锁定读:

  1. select * from table where id = X for update 对数据加X锁,其他事物不能对该行数据加任何锁。
  2. select * from table where id = X lock in share model 对数据加S锁,其他事务可以对其加S锁,但是加X锁会被阻塞。

以上加锁操作必须保证在一个事务当中,一旦事务提交后,锁即被释放掉。所以使用时不需使用begin、start transaction、set autocommit = 0。

1.4 自增长和锁

自增长是一种常见的使用方式,也是数据主键的首选。InnoDB对于每一个含有自增长属性的表都维护一个自增长计数器。会依据该计数器的值自动加1赋予自增长列。这种方式称作Auto Inc Locking,这是一种特殊的表锁机制,而这种方式存在一定的性能问题。

在mysql 5.1.22开始,提供了一种轻量级互斥量的自增长方式,这种机制大大提高了自增长值插入的性能。并且提供一个innodb_autoinc_lock_mode来控制自增长,默认为1。另外还有0和2两种方式。

0:并发性能不好,在5.1.22版本前使用。
1:默认值。
2:性能最高,并发插入会带来一定的问题,导致不连续。

二、锁的算法

2.1 三种行锁的算法:

1)Record Lock:单条记录锁。
2)Gap Lock:区间锁或间隙锁,锁定一个范围但不包含本身。
3)Next-key Lock:临键,Record Lock + Gap Lock,锁定范围区间的同时并且锁定记录本身。

如下索引值有1,5,9,11,name在三种锁的不同区间如下所示:

锁的区间

Next-key Lock算法是结合了record lock 和gap lock,其出现的原因是为了解决幻读(snapshot read),利用这种技术,锁定的不再是单个值,而是一个范围。

如果查询的索引含有唯一索引时,Next-key Lock将会降级为Record lock,仅锁住索引本身。

如果查询的索引是辅助索引,使用Next-key Lock进行加锁。按照上图给出下面一个sql,key是辅助索引,本例子不写唯一索引了:

select * from table where key = 5 for update;添加了X锁

那么会对5这个值增加(1,5]的前区间,还会使用gap lock对其增加一个后区间(5,9),因此,运行一下sql都会被阻塞:

select * from table where key = 6 lock in share mode;无法对X锁添加S锁
insert into table select 2;2在锁定区间,被阻塞
insert into table select 7;7在锁定区间,被阻塞

Gap Lock的作用是为了解决幻读问题,只在rr级别存在,如果想要关闭可以修改默认隔离界别为rc,但是这违反了隔离性。

在默认的隔离级别repeatable read下,Innodb使用next-key lock来解决幻读问题。幻读问题是指在同一事务的两次查询中,可能得到不同的结果,即第二次可能查询到之前不存在的行。

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

推荐阅读更多精彩内容