准备测试数据:

## 开启InnoDB Monitor
SET GLOBAL innodb_status_output=ON;
SET GLOBAL innodb_status_output_locks=ON; ## 创建测试表
DROP TABLE IF EXISTS tb1001; CREATE TABLE `tb1001` (
`order_id` INT(11) NOT NULL,
`order_num` INT(11) DEFAULT NULL,
`order_type` INT(11) DEFAULT NULL,
PRIMARY KEY (`order_id`),
KEY `idx_order_type` (`order_type`)
) ENGINE=INNODB DEFAULT CHARSET=utf8; ## 准备测试数据
INSERT INTO tb1001(order_id,order_num,order_type)
VALUES(10,10,10),(20,10,20),(21,10,20),(30,10,30),(40,10,40); ## 查看当前表数据
SELECT * FROM tb1001;
+----------+-----------+------------+
| order_id | order_num | order_type |
+----------+-----------+------------+
| 10 | 10 | 10 |
| 20 | 10 | 20 |
| 21 | 10 | 20 |
| 30 | 10 | 30 |
| 40 | 10 | 40 |
+----------+-----------+------------+

测试1:

## 先执行事务A
BEGIN;
SELECT * FROM tb1001 WHERE order_id<=10 FOR UPDATE; ## 再执行事务B
## 事务B被阻塞
BEGIN;
INSERT INTO tb1001(order_id,order_num,order_type)
VALUES(19,20,10)

锁阻塞信息如下:

SELECT *
FROM `information_schema`.`INNODB_LOCKS` \G
*************************** 1. row ***************************
lock_id: 1454153:29:3:3
lock_trx_id: 1454153
lock_mode: X,GAP
lock_type: RECORD
lock_table: `db001`.`tb1001`
lock_index: PRIMARY
lock_space: 29
lock_page: 3
lock_rec: 3
lock_data: 20
*************************** 2. row ***************************
lock_id: 1454152:29:3:3
lock_trx_id: 1454152
lock_mode: X
lock_type: RECORD
lock_table: `db001`.`tb1001`
lock_index: PRIMARY
lock_space: 29
lock_page: 3
lock_rec: 3
lock_data: 20 SELECT *
FROM `information_schema`.`INNODB_LOCK_WAITS` \G
*************************** 1. row ***************************
requesting_trx_id: 1454153
requested_lock_id: 1454153:29:3:3
blocking_trx_id: 1454152
blocking_lock_id: 1454152:29:3:3

绿色部分表示申请锁成功,黄色部分表示申请锁被阻塞。

使用SHOW ENGINE INNODB STATUS 查看,输出锁信息为:

---TRANSACTION 1454152, ACTIVE 38 sec
## SQL:
## BEGIN;
## SELECT * FROM tb1001 WHERE order_id<=10 FOR UPDATE; 2 LOCK struct(s), HEAP size 1136, 2 ROW LOCK(s)
MySQL thread id 1475204, OS thread handle 139581472573184, QUERY id 4425986 127.0.0.1 admin
TABLE LOCK TABLE `db001`.`tb1001` trx id 1454152 LOCK MODE IX
RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454152 lock_mode X
Record LOCK, HEAP NO 2 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 8000000a; ASC ;; order_id=10
1: len 6; HEX 00000016303e; ASC 0>;;
2: len 7; HEX f6000000320110; ASC 2 ;;
3: len 4; HEX 8000000a; ASC ;;
4: len 4; HEX 8000000a; ASC ;; Record LOCK, HEAP NO 3 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 80000014; ASC ;; order_id=20
1: len 6; HEX 00000016303e; ASC 0>;;
2: len 7; HEX f600000032011c; ASC 2 ;;
3: len 4; HEX 8000000a; ASC ;;
4: len 4; HEX 80000014; ASC ;; ---TRANSACTION 1454153, ACTIVE 17 sec inserting
## SQL:
## BEGIN;
## INSERT INTO tb1001(order_id,order_num,order_type)
## VALUES(19,20,10); mysql TABLES IN USE 1, locked 1
LOCK WAIT 2 LOCK struct(s), HEAP size 1136, 1 ROW LOCK(s)
MySQL thread id 1475203, OS thread handle 139581473105664, QUERY id 4425988 127.0.0.1 admin UPDATE
INSERT INTO tb1001(order_id,order_num,order_type)
VALUES(19,20,10) ------- TRX HAS BEEN WAITING 17 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454153 lock_mode X LOCKS gap BEFORE rec INSERT intention waiting
Record LOCK, HEAP NO 3 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 80000014; ASC ;; order_id=20
1: len 6; HEX 00000016303e; ASC 0>;;
2: len 7; HEX f600000032011c; ASC 2 ;;
3: len 4; HEX 8000000a; ASC ;;
4: len 4; HEX 80000014; ASC ;; ------------------
TABLE LOCK TABLE `db001`.`tb1001` trx id 1454153 LOCK MODE IX
RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454153 lock_mode X LOCKS gap BEFORE rec INSERT intention waiting
Record LOCK, HEAP NO 3 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 80000014; ASC ;; order_id=20
1: len 6; HEX 00000016303e; ASC 0>;;
2: len 7; HEX f600000032011c; ASC 2 ;;
3: len 4; HEX 8000000a; ASC ;;
4: len 4; HEX 80000014; ASC ;;

加锁详解:

## SQL
## BEGIN;
## SELECT * FROM tb1001 WHERE order_id<=10 FOR UPDATE; 在可重复读事务隔离级别下,由于 WHERE order_id<=10 需要对主键做范围扫描,使用加锁规则:
1、对满足条件的记录加Next-key锁。
2、从左向右扫描满足条件的记录,当遇到第一条不满足条件记录时,对该记录和该记录之前的间隙加锁(NEXT-KEY LOCK)。 加锁操作如下
1、当扫描到记录order_id=10时,满足条件,对记录order_id=10加Next-key锁,锁信息为:
RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454152 lock_mode X
Record LOCK, HEAP NO 2 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 8000000a; ASC ;; order_id=10
2、继续扫描到记录order_id=20时,第一条不满足条件的,对记录order_id=20加Next-key锁,锁信息为:
RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454152 lock_mode X
Record LOCK, HEAP NO 3 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
0: len 4; HEX 80000014; ASC ;; order_id=20 ## SQL
## BEGIN;
## insert into tb1001(order_id,order_num,order_type)
## values(19,20,10) INSERT加锁规则如下:
1、INSERT操作会对新插入的记录加行锁(ROW LOCK)+排他锁(X LOCK),不会产生任何GAP锁和Next-Key锁
2、在插入记录前,会向插入记录所在位置申请意向插入Gap锁(Insertion Intention Gap LOCK),相同区间的意向插入Gap锁不会冲突。
3、对于唯一索引,如果插入记录时表中已存在相同键值记录(被其他事务修改且未提交),即存在唯一键冲突,会尝试在已有记录上加读锁,然后等待。 加锁操作如下:
1、对表tb1001做数据插入操作,需要对表tb001上申请意向锁(TABLE LOCK TABLE `db001`.`tb1001` trx id 1454153 LOCK MODE IX)
2、向新记录order_id=19所在位置申请插入Gap锁(Insertion Intention Gap LOCK),但由于上面事务对记录order_id=20加Next-key锁,申请失败处于等待状态(lock_mode X LOCKS gap BEFORE rec INSERT intention waiting),等待锁信息为:

  Record LOCK, HEAP NO 3 PHYSICAL RECORD: n_fields 5; COMPACT FORMAT; info bits 0
  0: len 4; HEX 80000014; ASC ;; order_id=20

GAP LOCK /RECORD LOCK /NEXT KEY LOCK

在输出的锁信息中,如果仅对记录加行锁且未对记录前空间加GAP锁,则锁信息为:

RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454154 lock_mode X LOCKS rec but NOT gap

在输出的锁信息中,如果记录加行锁且对记录前空间加GAP锁,则锁信息为:

RECORD LOCKS SPACE id 29 page NO 3 n bits 80 INDEX PRIMARY of TABLE `db001`.`tb1001` trx id 1454152 lock_mode X

未显式指明"but NOT GAP"的RECORD LOCK实际上NEXT KEY LOCK。

在输出的锁信息中,如果未对记录加锁且仅对记录前空间加GAP锁,则锁信息为:

RECORD LOCKS space id 29 page no 3 n bits 80 index PRIMARY of table `db001`.`tb1001` trx id 1454596 lock_mode X locks gap before rec

MySQL Lock--MySQL加锁学习1的更多相关文章

  1. MySQL Lock--MySQL INSERT加锁学习

    准备测试数据: ## 开启InnoDB Monitor SET GLOBAL innodb_status_output=ON; SET GLOBAL innodb_status_output_lock ...

  2. 对mysql锁机制的学习

    1.对于mysql学习,经常翻看一些博客,论坛,好像或多或少有mysq锁机制的学习与总结,所以今天有必要 对mysql锁机制的一些个人的总结,以便以后深入的学习. 2.学习这件事,从来都是“深入浅出” ...

  3. 一条简单的更新语句,MySQL是如何加锁的?

    看如下一条sql语句: # table T (id )) delete : MySQL在执行的过程中,是如何加锁呢? 在看下面这条语句: : 那这条语句呢?其实这其中包含太多知识点了.要回答这两个问题 ...

  4. [MySQL] lock知识梳理

    MySQL Lock机制 INDEX: MySQL事务隔离级别 MVCC MySQL Lock类型 MySQL MDL CONTENT: 1. MySQL事务隔离级别 Read Uncommit RU ...

  5. MySQL实战45讲学习笔记:第三十九讲

    一.本节概况 MySQL实战45讲学习笔记:自增主键为什么不是连续的?(第39讲) 在第 4 篇文章中,我们提到过自增主键,由于自增主键可以让主键索引尽量地保持递增顺序插入,避免了页分裂,因此索引更紧 ...

  6. 【MySQL】MySQL无基础学习和入门之一:数据库基础概述和实验环境搭建

    数据库基础概述  大部分互联网公司都选择MySQL作为业务数据存储数据库,除了MySQL目前还有很多公司使用Oracle(甲骨文).SQLserver(微软).MongoDB等. 从使用成本来区分可以 ...

  7. 多IDC数据分布--MySQL多机房部署 - 学习笔记 - 51CTO技术博客

    多IDC数据分布--MySQL多机房部署 - 学习笔记 - 51CTO技术博客 多IDC数据分布--MySQL多机房部署

  8. MySQL事务控制语句(学习笔记)

    MySQL事务控制语句(学习笔记) MySQL事务控制语句         在mysql命令行的默认下,事务都是自动提交的,sql语句提交后马上会执行commit操作.因此开启一个事务必须使用begi ...

  9. 深挖计算机基础:MySQL实战45讲学习笔记

    参考极客时间专栏<MySQL实战45讲>学习笔记 一.基础篇(8讲) MySQL实战45讲学习笔记:第一讲 MySQL实战45讲学习笔记:第二讲 MySQL实战45讲学习笔记:第三讲 My ...

随机推荐

  1. PostgreSQL中的一些日志

    1.Write Ahead Log(WAL日志)预写日志(WAL)是保证数据完整性的标准方法.在有关交易处理的大多数(如果不是全部)书籍中都可以找到详细说明. 简而言之,WAL的核心概念是,只有在记录 ...

  2. odoo开发笔记--ValueError Expected singleton

    异常处理参考:https://stackoverflow.com/questions/31070640/valueerror-expected-singleton-odoo8 报错: ValueErr ...

  3. unable to lock the administration错误解决

    在ubantu系统上,使用 apt-get 命令或者其相对更新的APT 管理工具时,遇到 unable to lock the administration directory (/var/lib/d ...

  4. Spring cloud微服务安全实战-7-11PinPoint+SpringBoot环境搭建

    微服务的最后一个组件, 调用链监控,一个请求进来以后,经过N多个微服务,例如a调用了b.b又调用了c,那么在这个过程中看到,整个的调用的链路,然后每一段调用所耗费的时间,帮你去分析你的系统如果出现瓶颈 ...

  5. Shell流程控制语句if

    (1).if语句 语法格式: if 判断条件 ; then 命令 fi 或 if 判断条件 then 命令 fi if语句流程图: 实例:判断命令是否执行成功,成功则输出语句This is ok. [ ...

  6. c-lodop回调函数简短问答及相关博文

    回调函数相关博文:C-Lodop回调函数的触发.LODOP.FORMAT格式转换[回调和直接返回值].Lodop导出excel及提示成功[回调和直接返回值].c-lodop获取任务页数-回调里给全局变 ...

  7. Kubernetes StatefulSet

    StatefulSet 简介 在Kubernetes中,Pod的管理对象RC.Deployment.DaemonSet和Job都是面向无状态的服务.但现实中有很多服务是有状态的,特别是一些复杂的中间件 ...

  8. Python Tkinter 窗口创建与布局

    做界面,首先需要创建一个窗口,Python Tkinter创建窗口很简单:(注意,Tkinter的包名因Python的版本不同存在差异,有两种:Tkinter和tkinter,读者若发现程序不能运行, ...

  9. PHP字符串替换

    $pid = str_replace(',',',',$pid); $pid = str_replace(' ','',$pid); $pid = str_replace(array(',', ' ' ...

  10. 【LeetCode】 #9:回文数 C语言

    目录 题目 思路 初步想法 进一步想法 最后想法 总结 最近打算练习写代码的能力,所以从简单题开始做. 大部分还是用C语言来解决. @(解法) 题目 判断一个整数是否是回文数.回文数是指正序(从左向右 ...