当 Mysql - InnoDB 行锁遇到复合主键和多列索引

背景

今天在配合其他项目组做系统压测,过程中出现了偶发的死锁问题。分析代码后发现有复合主键的 update 情况,更新复合主键表时只使用了一个字段更新,同时在事务内又有对该表的 insert 操作,结果出现了偶发的死锁问题。

比如表t_lock_test中有两个主键都为 primary key(a,b),但是更新时却通过update t_lock_test .. where a = ?,然后该事务内又有insert into t_lock_test values(...)

InnoDB 中的锁算法是Next-Key Locking,很可能是因为这个点导致的死锁,但是复合主键下会触发Next-Key Locking吗,那多列联合 unique 索引下又会触发Next-Key Locking吗,书上并没有找到答案,得实际测试一下。

InnoDB 中的锁

锁是数据库系统区别于文件系统的一个关键特性。锁机制用于管理对共享资源的并发访 [插图]。InnoDB 存储引擎会在行级别上对表数据上锁,这固然不错。不过 InnoDB 存储引擎也会在数据库内部其他多个地方使用锁,从而允许对多种不同资源提供并发访问。例如,操作缓冲池中的 LRU 列表,删除、添加、移动 LRU 列表中的元素,为了保证一致性,必须有锁的介入。数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性。

由于使用锁时基本都是在 InnoDB 存储引擎下,所以跳过 MyISAM,直接讨论 InnoDB。

锁类型

InnoDB 存储引擎实现了如下两种标准的行级锁:

  • 共享锁 (S Lock),允许事务读一行数据
  • 排它锁 (x lOCK),允许事务删除或更新一条数据

如果一个事务 T1 已经获得了 r 的共享锁,那么另外的事务 T2 可以立即获得行 r 的共享锁,因为读取并没有改变 r 的数据,成这种情况为锁兼容(Lock Compatible)。但若有其他的事务 T3 箱获得行 r 的排它锁,则其必须等待 T1、T2 释放行 r 上的共享锁 —— 这种情况称为锁不兼容。

排它锁和共享锁的兼容性:

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

InnoDB 中对数据进行 UPDATE/DELETE 操作会产生行锁,也可以显示的添加行锁(也就是平时所说的 “悲观锁”)

select for update
lock in share mode

锁算法

InnoDB 有 3 种行锁的算法,其分别是:

Record Lock:单个行记录上的锁,就是字面意思的行锁

Record Lock 会锁住索引记录 (注意这里说的是索引,因为 InnoDB 下主键索引即数据), 如果 InnoDB 存储引擎表在建立的时候没有设置任何一个索引,那么这时对 InnoDB 存储引擎会使用隐式的主键来进行锁定。

Gap Lock:间隙锁,锁定一个
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值