InnoDB存储引擎的行级锁

InnoDB存储引擎和MyISAM的其中有两个很重要的区别:一个是事务,一个就是锁机制不同。事务之前有介绍,有问题的去补课;锁方面的不同是InnoDB引擎既有表锁又有行锁,表锁的应用和MyISAM表锁用法一样,行锁只有通过有索引的字段作为条件检索的时候,才会使用行级锁,反之则是表锁。

一、隐式加锁

创建表和测试数据

用户表user中id为主键索引,username为普通索引,money字段为普通字段。在非事务环境下,隐式加锁的过程时间非常短,不便研究。下面的栗子都是在事务环境下

CREATE TABLE `user`(
id INT PRIMARY KEY AUTO_INCREMENT,
`username` VARCHAR(50),
`money` DECIMAL(7,2),
key username(username)
)ENGINE=innodb CHARSET=utf8;
INSERT INTO user(`username`,`money`) VALUES('乔峰',5);
INSERT INTO user(`username`,`money`) VALUES('风清扬',20);
INSERT INTO user(`username`,`money`) VALUES('聂哥',88); 

1、行锁

当我们对用户表进行增删改(insert、delete、update)的时候,如果有检索条件中使用到了索引,MySQL服务器会自动给当前操作的表添加行锁。

A端

更新id为3的记录,id为主键索引,所以会引发行级锁。

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> update user set money=money+5 where id=3;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0

B端在执行update操作的时候,先是光标不停闪烁,且进入锁等待状态,后报锁超时错误

mysql> update user set money=money+5 where id=1;
Query OK, 1 row affected (0.08 sec)
Rows matched: 1 Changed: 1 Warnings: 0
​
mysql> update user set money=money+12 where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
A端

A端执行提交(commit),系统会自动释放表锁

mysql> commit;
Query OK, 0 rows affected (0.03 sec) 

2、表锁

如果有检索条件(money字段)中没有使用到了索引,MySQL服务器会自动给当前操作的表添加表锁。

A端
mysql> select * from user;
+----+----------+-------+
| id | username | money |
+----+----------+-------+
| 1 | 乔峰 | 10.00 |
| 2 | 风清扬 | 20.00 |
| 3 | 聂哥 | 93.00 |
+----+----------+-------+
3 rows in set (0.02 sec)
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> update user set money=money+5 where money=93.00;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1 Changed: 1 Warnings: 0 
B端
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> update user set money=money+12 where id=2;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql> update user set money=money+12 where id=1;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
mysql>
​

二、显式加行锁

加锁语句:

SELECT 查询语句 LOCK IN SHARE MODE | FOR UPDATE  

我们只需在正常的查询语句后面加LOCK IN SHARE MODE | FOR UPDATE就能实现添加行级读锁和行级排他锁

1、意向锁

意向锁是InnoDB自动加的,不需用户干预,对于UPDATE、DELETE、INSERT操作,InnoDB会自动给操作的数据加排他锁。 我们在显式加行锁的时候,MySQL服务器会自动给操作表添加一个意向锁。此意向锁是隐式添加的,多个意向锁之间不会产生冲突且相互兼容

2、锁的兼容问题

- 共享锁 排他锁 意向共享锁 意向排他锁
共享锁 兼容 冲突 兼容 冲突
排他锁 冲突 冲突 冲突 冲突

2.1、共享锁兼容

A端

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> select * from user lock in share mode;
+----+----------+-------+
| id | username | money |
+----+----------+-------+
| 1 | 乔峰 | 10.00 |
| 2 | 风清扬 | 20.00 |
| 3 | 聂哥 | 98.00 |
+----+----------+-------+
3 rows in set (0.00 sec) 

B端

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> select * from user lock in share mode;
+----+----------+-------+
| id | username | money |
+----+----------+-------+
| 1 | 乔峰 | 10.00 |
| 2 | 风清扬 | 20.00 |
| 3 | 聂哥 | 98.00 |
+----+----------+-------+
3 rows in set (0.00 sec)

2.2、共享锁和意向排他锁冲突

A端

mysql> select * from user where id=3 lock in share mode;
+----+----------+-------+
| id | username | money |
+----+----------+-------+
| 3 | 聂哥 | 98.00 |
+----+----------+-------+
1 row in set (0.00 sec)
​
mysql> update user set money=money+5 where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction 

2.3、排他锁与其他锁都冲突

A端

mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> select * from user where id=3 for update;
+----+----------+--------+
| id | username | money |
+----+----------+--------+
| 3 | 聂哥 | 103.00 |
+----+----------+--------+
1 row in set (0.00 sec) 

B端

mysql> select * from user where id=3 lock in share mode;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
​
mysql> update user set money=money+5 where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

三、间隙锁

间隙锁是针对一个范围条件的检索时,InnoDB会给符合条件的已有的数据记录的索引项加锁;对于键值在条件范围内但是并不存在的记录,叫做“间隙”,InnoDB也会对这个“间隙”加锁,这种锁机制就是间隙锁

A端
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
​
mysql> select * from user where id > 2 for update;
+----+----------+--------+
| id | username | money |
+----+----------+--------+
| 3 | 聂哥 | 103.00 |
+----+----------+--------+
1 row in set (0.00 sec)
B端
mysql> update user set money=money+5 where id=3;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
​
mysql> INSERT INTO user(`username`,`money`) VALUES('jack',99);
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
 

 
 

InnoDB存储引擎的行级锁的更多相关文章

  1. 三分钟入门 InnoDB 存储引擎中的表锁和行锁

    各位对 "锁" 这个概念应该都不是很陌生吧,Java 语言中就提供了两种锁:内置的 synchronized 锁和 Lock 接口,使用锁的目的就是管理对共享资源的并发访问,保证数 ...

  2. InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁!

    InnoDB行锁是通过索引上的索引项来实现的,这一点MySQL与Oracle不同,后者是通过在数据中对相应数据行加锁来实现的. InnoDB这种行锁实现特点意味者:只有通过索引条件检索数据,InnoD ...

  3. mysql中InnoDB存储引擎的行锁和表锁

    Mysql的InnoDB存储引擎支持事务,默认是行锁.因为这个特性,所以数据库支持高并发,但是如果InnoDB更新数据的时候不是行锁,而是表锁的话,那么其并发性会大打折扣,而且也可能导致你的程序出错. ...

  4. MySQL技术内幕InnoDB存储引擎(六)——锁

    什么是数据库的锁? 锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访问.让数据库事务满足隔离性的要求. InnoDB 中锁的作用 不仅用于对数据进行并发访问,还还包括了缓冲 ...

  5. Mysql的行级锁与表级锁

    在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM ...

  6. Mariadb之显式使用表锁和行级锁

    首先我们来看看mariadb的锁定概念,所谓锁就是当一个进程或事务在操作某一资源时,为了防止其他用户或者进程或事务对其进行资源操作,导致资源抢占而发生冲突,通常在A进程操作该资源时,会对该资源进行加锁 ...

  7. InnoDB存储引擎

    [InnoDB和MyISAM区别][ http://jeck2046.blog.51cto.com/184478/90499] InnoDB和MyISAM是许多人在使用MySQL时最常用的两个表类型, ...

  8. 【MySQL】MySQL(四)存储引擎、索引、锁、集群

    MySQL存储引擎 MySQL体系结构 体系结构的概念 任何一套系统当中,每个部件都能起到一定的作用! MySQL的体系结构 体系结构详解 客户端连接 支持接口:支持的客户端连接,例如C.Java.P ...

  9. MySQL InnoDB存储引擎中的锁机制

    1.隔离级别 Read Uncommited(RU):这种隔离级别下,事务间完全不隔离,会产生脏读,可以读取未提交的记录,实际情况下不会使用. Read Committed (RC):仅能读取到已提交 ...

  10. MySQL 温故而知新--Innodb存储引擎中的锁

    近期碰到非常多锁问题.所以攻克了后,细致再去阅读了关于锁的书籍,整理例如以下:1,锁的种类 Innodb存储引擎实现了例如以下2种标准的行级锁: ? 共享锁(S lock),同意事务读取一行数据. ? ...

随机推荐

  1. 解决SUM函数返回为NULL

    解决SUM函数返回为NULL SUM函数的作用:计算某一字段中所有行的数值和, 使用SUM函数进行对符合条件的结果行数进行求和. 问题产生: sum 求和时会对 null 进行过滤,不计算,但如果没有 ...

  2. 开源:Taurus.DTS 微服务分布式任务框架,支持即时任务、延时任务、Cron表达式定时任务和广播任务。

    前言: 在发布完:开源:Taurus.DTC 微服务分布式事务框架,支持 .Net 和 .Net Core 双系列版本,之后想想,好像除了事务外,感觉里面多了一个任务发布订阅的基础功能. 本想既然都有 ...

  3. Django 对实体的增删改查样例

    class UserInfo(models.Model): """ 人员信息 """ user_id = models.CharField( ...

  4. 面试官:SpringBoot如何实现缓存预热?

    缓存预热是指在 Spring Boot 项目启动时,预先将数据加载到缓存系统(如 Redis)中的一种机制. 那么问题来了,在 Spring Boot 项目启动之后,在什么时候?在哪里可以将数据加载到 ...

  5. [译] kubernetes:kube-scheduler 调度器代码结构概述

    本文翻译自 https://github.com/kubernetes/community/blob/master/contributors/devel/sig-scheduling/scheduli ...

  6. 碎碎念 | 20230326 · 与 SEU & 南传跆协共进晚餐

    (碎碎念)今天晚上跟社团一起吃饭,南传的跆协来交流了.南传的人说 他们基本散养,没人正经自习 图书馆基本废弃,校园里有一个大舞台 每天表演,大家每天写剧本 / 演绎 / 拍摄 剪辑,天天喝庆功酒()然 ...

  7. jedis 与 redission 实现分布式锁

    本文为博主原创,未经允许不得转载: 目录: 1. Jedis 实现分布式锁 2. Redission 实现分布式锁 为了确保分布式锁可用,至少要保证锁的实现同时满足以下几个条件 互斥性:在任意时刻只有 ...

  8. Shell-流程控制-if-then-elif

  9. [转帖]HTTP状态码、请求方法、响应头信息

    https://www.cnblogs.com/pachongshangdexuebi/p/5279608.html HTTP状态码 当浏览者访问一个网页时,浏览者的浏览器会向网页所在服务器发出请求. ...

  10. [转帖]Linux 防火墙开放特定端口 (iptables)

    查看状态: iptables -L -n 下面添加对特定端口开放的方法: 使用iptables开放如下端口 /sbin/iptables -I INPUT -p tcp --dport 8000 -j ...