mysql自增主键死锁_<mysql>insert居然还会死锁??又学到了。。。

为什么你的insert就死锁了

一、前言

本以为只需要系统学习一个较完全的逻辑,但是实际牵扯很多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,分别对应”传统模式”, “连续模式”, “交错模式”。

传统模式:涉及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锁:selec

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值