美文网首页DataBase
InnoDB存储引擎行级锁引起锁争用问题

InnoDB存储引擎行级锁引起锁争用问题

作者: 何甜甜在吗 | 来源:发表于2017-12-07 23:20 被阅读0次

在事务中执行select…for update,update,delete会引起锁,对于事务的修改,事务中会使用X锁,X锁是行级锁,InnDB行锁是通过给索引上的索引项加锁实现的(只有通过索引条件检索数据(即explain sql语句,type=index或range),InnoDB才使用行级锁,否则使用表锁)

为了验证这个,我做了一个小测验

数据表t_bitfly:

CREATE TABLE `t_bitfly` (
  `id` bigint(20) NOT NULL DEFAULT '0',
  `value` varchar(32) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

session1:

start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_bitfly where id < 4 for update;
+----+-------+
| id | value |
+----+-------+
|  1 | a     |
|  2 | b     |
|  3 | c     |
+----+-------+
3 rows in set (0.00 sec)

session2:

start transaction;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from t_bitfly where id >= 4 for update;
select * from t_bitfly where id >= 4 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

出现死锁

此刻我的心情

想不明白啊,不是应该只锁住<4的那几行吗

explain:

mysql> explain select * from t_bitfly where id < 4\G;
*************************** 1\. row ***************************
           id: 1
  select_type: SIMPLE
        table: t_bitfly
   partitions: NULL
         type: range
possible_keys: PRIMARY
          key: PRIMARY
      key_len: 8
          ref: NULL
         rows: 3
     filtered: 100.00
        Extra: Using where; Using index

type=range,使用上索引了啊,为什么,为什么,不明白啊

我的心情

这个问题困扰自己好久,终于在今天晚上找到答案了,恍然大悟的感觉真的是贼爽

原因:在UPDATE、DELETE操作时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking。

继续做测验

session2:

start transaction;
    Query OK, 0 rows affected (0.00 sec)
    mysql> select * from t_bitfly where id > 5 for update;
    mysql> select * from t_bitfly where id > 4 for update;
+----+-------+
| id | value |
+----+-------+
|  5 | e     |
|  6 | f     |
|  7 | g     |
|  8 | h     |
|  9 | i     |
| 10 | j     |
| 11 | k     |
+----+-------+
7 rows in set (0.00 sec)

现在就不出现死锁的情况下,因为此时没有包括4

出现next-key有两种情况,一是上面的使用索引范围,二是使用相等条件请求给一个不存在的记录:
例如:

session 1:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from t_bitfly where id = 17 for update;
Empty set (0.00 sec)

session 2:

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t_bitfly values(17,'n');
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

一般情况下相等情况不会出现锁争用问题

使用next-key的目的:
1)解决幻读
2)满足mysql的复制和恢复

带来的问题
造成严重的锁等待

如何解决:
尽量避免使用范围条件,使用相等条件来访问和更新数据

行锁的使用还需要注意的几点,否则很有可能会在执行的时候出现死锁或获取不到锁的情况(比如我遇到的):

1)在MySQL中,行级锁并不是直接锁记录,而是锁索引。

2)索引分为主键索引和非主键索引两种,如果一条sql语句操作了主键索引,MySQL就会锁定这条主键索引;如果一条语句操作了非主键索引(自定义索引+主键),MySQL会先锁定该非主键索引,再锁定相关的主键索引

3)当两个事务同时执行,一个锁住了主键索引,在等待其他相关索引。另一个锁定了非主键索引,在等待主键索引。这样就会发生死锁

相关文章

  • InnoDB存储引擎行级锁引起锁争用问题

    在事务中执行select…for update,update,delete会引起锁,对于事务的修改,事务中会使用X...

  • Innodb的锁

    Innodb的锁是行级锁 mysql delete是否会锁表 MySQL的InnoDB存储引擎支持行级锁,Inno...

  • MySQL的锁分类以及使用场景

    myisam存储引擎默认是表级锁innodb存储引擎默认是行级锁DBD存储引擎默认是页面锁表级锁:开销小,加锁快;...

  • MySQL 锁问题

    MyISAM 和 MEMORY 存储引擎采用的是表级锁;InnoDB 存储引擎即支持行级锁,也支持表级锁,但默认情...

  • 3.行级锁

    行级锁介绍 InnoDB存储引擎实现 一. InnoDB的行级锁,按照锁定范围来说,分为三种: 1.记录锁(Rec...

  • mysql规范

    一、基础规范【强制】使用InnoDB存储引擎解读:InnoDB存储引擎是MySQL默认存储引擎,支持事务和行级锁,...

  • 数据库基础

    1 锁 1.1 InnoDB的锁 行级锁(InnoDB存储引擎实现了两种标准的)共享锁 允许事务读一行数据排他锁 ...

  • 深入理解MySQL

    存储引擎 现在常用的存储引擎是InnoDB,以前常用的是MyISAM。 InnoDB 支持事务、支持行级锁、支持外...

  • 【原创】因酷数据库开发规范

    基本规范 所有表必须使用Innodb存储引擎Innodb存储引擎是Mysql5.6以后默认引擎支持事务,行级锁,更...

  • 15.mysql锁问题(2)-InnoDB

    5. InnoDB 行锁 5.1 行锁介绍 行锁特点 :偏向InnoDB 存储引擎,开销大,加锁慢;会出现死锁;锁...

网友评论

    本文标题:InnoDB存储引擎行级锁引起锁争用问题

    本文链接:https://www.haomeiwen.com/subject/cdckixtx.html