前段时间系统老是出现insert死锁,很是纠结。经过排查发现是间隙锁!间隙锁是innodb中行锁的一种, 但是这种锁锁住的却不止一行数据,他锁住的是多行,是一个数据范围。间隙锁的主要作用是为了防止出现幻读,但是它会把锁定范围扩大,有时候也会给我们带来麻烦,我们就遇到了。 在数据库参数中, 控制间隙锁的参数是:innodb_locks_unsafe_for_binlog, 这个参数默认值是OFF, 也就是启用间隙锁, 他是一个bool值, 当值为true时表示disable间隙锁。那为了防止间隙锁是不是直接将innodb_locaks_unsafe_for_binlog设置为true就可以了呢? 不一定!而且这个参数会影响到主从复制及灾难恢复, 这个方法还尚待商量。
间隙锁的出现主要集中在同一个事务中先delete 后 insert的情况下, 当我们通过一个参数去删除一条记录的时候, 如果参数在数据库中存在, 那么这个时候产生的是普通行锁, 锁住这个记录, 然后删除, 然后释放锁。如果这条记录不存在,问题就来了, 数据库会扫描索引,发现这个记录不存在, 这个时候的delete语句获取到的就是一个间隙锁,然后数据库会向左扫描扫到第一个比给定参数小的值, 向右扫描扫描到第一个比给定参数大的值, 然后以此为界,构建一个区间, 锁住整个区间内的数据, 一个特别容易出现死锁的间隙锁诞生了。
举个例子:
表task_queue
Id taskId
1 2
3 9
10 20
40 41
开启一个会话: session 1
##
sql> delete from task_queue where taskId = 20;
sql> insert into task_queue values(20, 20);
在开启一个会话: session 2
##
sql> delete from task_queue where taskId = 25;
sql> insert into task_queue values(30, 25);
在没有并发,或是极少并发的情况下, 这样会可能会正常执行,在Mysql中, 事务最终都是穿行执行, 但是在高并发的情况下, 执行的顺序就极有可能发生改变, 变成下面这个样子:
sql> delete from task_queue where taskId = 20;
sql> delete from task_queue where taskId = 25;
sql> insert into task_queue values(20, 20);
sql> insert into task_queue values(30, 25);
这个时候最后一条语句:insert into task_queue values(30, 25); 执行时就会爆出死锁错误。因为删除taskId = 20这条记录的时候,20 -- 41 都被锁住了, 他们都取得了这一个数据段的共享锁, 所以在获取这个数据段的排它锁时出现死锁。
这种问题的解决办法:前面说了, 通过修改innodb_locaks_unsafe_for_binlog参数来取消间隙锁从而达到避免这种情况的死锁的方式尚待商量, 那就只有修改代码逻辑, 存在才删除,尽量不去删除不存在的记录。
相关推荐
在为一个客户排除死锁问题时我遇到了一个有趣的包括InnoDB间隙锁的情形。对于一个WHERE子句不匹配任何行的非插入的写操作中,我预期事务应该不会有锁,但我错了。让我们看一下这张表及示例UPDATE。 mysql> SHOW...
4. **间隙锁(Gap Locks)和Next-Key Locks**:为了防止“幻读”问题,InnoDB会自动在会话事务中加上间隙锁,锁定数据行之间的“间隙”,并使用Next-Key Locks来锁定索引键及其之前的数据项,从而保证数据的一致性。...
MySQL的InnoDB存储引擎在处理...例如,死锁日志分析、事务隔离级别的选择以及如何处理间隙锁问题,都需要深入理解这些锁的工作原理。通过适当调整事务策略和查询方式,可以减少锁冲突,提高数据库系统的并发处理能力。
- **临键锁(Next-key Locks)**:结合记录锁和间隙锁,锁定索引记录和其前后间隙,防止幻读。 - **插入意向锁(Insert Intention Locks)**:在插入新记录前设置,表明即将插入,避免与其他锁冲突。 - **自增锁...
InnoDB的行级锁不仅包括记录锁,还包括间隙锁(Next-Key Lock)。如果事务A持有记录A的行锁和记录B与记录C之间的间隙锁,而事务B则持有记录B的行锁和记录C与记录D之间的间隙锁,当两者试图获取对方持有的锁时,也会...
今天来分享一下我在线上环境遇到的有关MySQL间隙锁的死锁问题。本文将讲述从发现问题到解决问题的全过程,并给出一些个人建议,其中使用的数据将做脱敏处理,但不影响食用口感。 发现问题 运维同学发现有大量的MySQL...
在实际中,解决MySQL(InnoDB)的死锁问题需要深入了解死锁产生的原因、锁的类型以及加锁策略,进而对业务逻辑进行优化或调整数据库配置和代码逻辑以减少死锁的可能性。 ### 个人简介 何登成作为阿里巴巴DBA团队的...
3. **间隙锁(Gap Locks)与Next-Key Locks**:InnoDB还使用间隙锁来防止插入到已排序索引记录间的空隙,以及防止幻读。Next-Key Lock是记录锁和间隙锁的组合,防止在索引区间内的插入。 4. **死锁(Deadlocks)**...
- **Next-Key锁**:InnoDB为了防止幻读现象而引入的锁,实际上是一种行锁和间隙锁的组合。 **3、验证案例** 假设有一个简单的表`orders`,包含`order_id`和`status`两列。 - **共享锁验证**: - 在会话A中,对某...
本文主要讨论了MySQL中的五种锁:表锁、行锁、共享锁、排它锁和间隙锁。 1. 表锁:表锁是MySQL中最基础的锁类型,主要在MyISAM存储引擎中使用。表锁分为两种模式:读锁(Table Read Lock)和写锁(Table Write Lock...
- **Next-Key Locks**:结合了行锁和间隙锁,防止幻读。它锁定指定的行,同时锁定该行前后的间隙,避免其他事务在此范围内插入数据。 通过示例代码,我们可以观察到不同隔离级别下的事务行为。例如,在`READ ...
InnoDB提供了多种锁机制,包括行级锁、表级锁和间隙锁。行级锁提高了并发性能,因为它只锁定特定的行,而不是整个表。表级锁则在处理大量数据或批量操作时更有效。间隙锁防止其他事务在锁定范围内插入新记录,确保...
在MySQL中,锁机制是保障数据操作安全的重要组成部分,其主要分为表锁、行锁和间隙锁。本知识点详细解读了MySQL锁机制的定义、分类、特点以及具体的应用案例。 1. 锁的定义和分类 在数据库系统中,锁是用来控制多...
21.MySQL高级锁InnoDB行锁间隙锁危害.avi 22.MySQL高级锁InnoDB行锁争用情况查看.avi 23.MySQL高级锁InnoDB行锁总结.avi 24.MySQL高级SQL技巧SQL执行顺序及正则表达式.avi 25.MySQL高级SQL技巧数字函数与字符串函数....
在MySQL的InnoDB存储引擎中,插入操作不仅涉及到行级锁,还可能涉及Gap锁和Next-Key Locks,这些锁机制的设计是为了防止幻读(Phantom Read)和其他并发问题。 1. 数据库版本:文中提到的是MySQL 5.6.27。不同版本...
**间隙锁**用于锁定一个范围内的所有行,而不是具体的某一行。 **作用**: - 主要是为了防止幻读问题(即在两次查询之间出现新的行)。 - 例如,在执行查询`SELECT * FROM t WHERE id 时,除了锁定符合条件的实际行...