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. 十三、docker的四种网络类型

    系列导航 一.docker入门(概念) 二.docker的安装和镜像管理 三.docker容器的常用命令 四.容器的网络访问 五.容器端口转发 六.docker数据卷 七.手动制作docker镜像 八 ...

  2. S3C2440移植uboot之裁剪和修改默认参数

      上一节S3C2440移植uboot之支持DM9000移植uboot支持了网卡驱动,这节裁剪和修改uboot默认参数 目录 uboot的环境参数 修改uboot的默认环境变量 查看 default_ ...

  3. 每天学五分钟 Liunx 0010 | 软件篇: RPM 和 YUM

    1. RPM RPM(RedHat Package Manager),顾名思义是 RedHat 的软件包管理器.它遵循 GPL 规则且功能强大好用,从而逐渐运用到其它 Liunx 发行版中,包括 Fe ...

  4. kafka 在 zookeeper 中保存的数据内容

    转载请注明出处: 1. 服务器上下载 kafka : wget https://archive.apache.org/dist/kafka/2.4.0/kafka_2.12-3.2.0.tgz 2.  ...

  5. 【日常踩坑】解决 kex_exchange_identification 报错

    目录 踩坑 原因分析 解决办法 1. 临时关闭代理 2. 修改代理软件配置,22 端口走直连 3. 改用 HTTPS 协议,走 443 端口 参考资料 踩坑 最近在使用 git 时,发现 git pu ...

  6. Pgsql之查询一个月份的天数

    前几天干活儿的时候,项目中有这么个需求,需要用pgsql查询某个月份有多少天,下面贴代码: select date_part('days', date_trunc('month', to_timest ...

  7. MyBatis06——动态SQL

    动态SQL if choose (when, otherwise) trim (where, set) foreach 搭建环境 1.搭建数据库 CREATE TABLE `blog` ( `id` ...

  8. [转帖]部署Alertmanager

    https://flashcat.cloud/docs/content/flashcat-monitor/prometheus/alert/manager-install/ Alertmanager和 ...

  9. [转帖]Linux—CPU核数、上下文切换介绍及pidstat等命令详解

    https://www.jianshu.com/p/0ae0c1153c34 关注:CodingTechWork,一起学习进步. 引言 并发编程   并发编程的目的是为了改善串行程序执行慢问题,但是, ...

  10. [转帖]Kafka关键参数设置

    https://www.cnblogs.com/wwcom123/p/11181680.html 生产环境中使用Kafka,参数调优非常重要,而Kafka参数众多,我们的java的Configurat ...