oppoJava面试题,为什么你的insert就死锁了

本文详细探讨了MySQL InnoDB引擎中,insert操作如何导致死锁,涉及事务隔离级别、间隙锁、插入意向锁及其作用。通过案例分析了唯一键冲突和间隙锁冲突时的死锁场景,旨在帮助读者理解数据库锁机制和优化并发插入的策略。
摘要由CSDN通过智能技术生成

一、前言

本以为只需要系统学习一个较完全的逻辑,但是实际牵扯很多innodb锁相关知识及加锁方式。我好像并没有那么大的能耐,把各种场景的加锁过程一一列举并加之分析;亦没有太多的精力验证网上的言论的准确性。

只好根据现在了解的内容,参考官方文档,说说自己当前的理解。 本文仅供参考。

二、现场状态

不同的mysql版本,不同的参数设置,都可能对加锁过程有影响。 分析加锁机制还是应当尽可能多地列举一下关键参数,例如:当前mysql版本、事务隔离级别等。 如下,仅仅只列出个别比较重要的参数。

1.数据库版本

``mysql> select version();
+-----------+
| version() |
+-----------+
| 5.6.27 |
+-----------+

2. 数据库引擎

``mysql> show variables like '%engine%';
+----------------------------+--------+
| Variable_name | Value |
+----------------------------+--------+
| default_storage_engine | InnoDB |
| default_tmp_storage_engine | InnoDB |
| storage_engine | InnoDB |
+----------------------------+--------+

注:InnoDB支持事务,Myisam不支持事务;InnoDB支持行锁和表锁;Myisam不支持行锁。

3. 事务隔离级别

``mysql> select @@global.tx_isolation, @@session.tx_isolation, @@tx_isolation;
+-----------------------+------------------------+-----------------+
| @@global.tx_isolation | @@session.tx_isolation | @@tx_isolation |
+-----------------------+------------------------+-----------------+
| REPEATABLE-READ | REPEATABLE-READ | REPEATABLE-READ |
+-----------------------+------------------------+-----------------+

注:几种事务隔离级别:READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE

4. 查看gap锁开启状态

``mysql> show variables like 'innodb_locks_unsafe_for_binlog';
+--------------------------------+-------+
| Variable_name | Value |
+--------------------------------+-------+
| innodb_locks_unsafe_for_binlog | OFF |
+--------------------------------+-------+

innodb_locks_unsafe_for_binlog:默认值为0,即启用gap lock。 最主要的作用就是控制innodb是否对gap加锁。 但是,这一设置变更并不影响外键和唯一索引(含主键)对gap进行加锁的需要。 开启innodb_locks_unsafe_for_binlog的REPEATABLE-READ事务隔离级别,很大程度上已经蜕变成了READ-COMMITTED。

参见官方文档1

By default, the value of innodb_locks_unsafe_for_binlog is 0 (disabled), which means that gap locking is enabled: InnoDB uses next-key locks for searches and index scans. To enable the variable, set it to 1. This causes gap locking to be disabled: InnoDB uses only index-record locks for searches and index scans.

Enabling innodb_locks_unsafe_for_binlog does not disable the use of gap locking for foreign-key constraint checking or duplicate-key checking.

The effect of enabling innodb_locks_unsafe_for_binlog is similar to but not identical to setting the transaction isolation level to READ COMMITTED.

5. 查看自增锁模式

``mysql> show variables like 'innodb_autoinc_lock_mode';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_autoinc_lock_mode | 1 |
+--------------------------+-------+

innodb_autoinc_lock_mode有3种配置模式:0、1、2,分别对应”传统模式”, “连续模式”, “交错模式”。8 传统模式:涉及auto-increment列的插入语句加的表级AUTO-INC锁,只有插入执行结束后才会释放锁。这是一种兼容MySQL 5.1之前版本的策略。 连续模式:可以事先确定插入行数的语句(包括单行和多行插入),分配连续的确定的auto-increment值;对于插入行数不确定的插入语句,仍加表锁。这种模式下,事务回滚,auto-increment值不会回滚,换句话说,自增列内容会不连续。 交错模式:同一时刻多条SQL语句产生交错的auto-increment值。

由于insert语句常常涉及自增列的加锁过程,会涉及到AUTO-INC Locks加锁过程。 为了分步了解insert加锁过程,本文暂不讨论任何涉及自增列的加锁逻辑。 这一参数设置相关内容可能会出现在我的下一篇文章里。

三、InnoDB锁类型2

1. 基本锁

基本锁:共享锁(Shared Locks:S锁)与排他锁(Exclusive Locks:X锁)

mysql允许拿到S锁的事务读一行,允许拿到X锁的事务更新或删除一行。 加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁; 加了X锁的记录,不允许其他事务再加S锁或者X锁。

mysql对外提供加这两种锁的语法如下: 加S锁:select…lock in share mode 加X锁:select…for update

2. 意向锁(Intention Locks)

InnoDB为了支持多粒度(表锁与行锁)的锁并存,引入意向锁。 意向锁是表级锁,可分为意向共享锁(IS锁)和意向排他锁(IX锁)。

InnoDB supports multiple granularity locking which permits coexistence of row-level locks and locks on entire tables. To make locking at multiple granularity levels practical, additional types of locks called intention locks are used.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值