准备工作

创建表 tb_innodb_lock

drop table if exists test_innodb_lock;

CREATE TABLE test_innodb_lock (

a INT (11),

b VARCHAR (20)

) ENGINE INNODB DEFAULT charset = utf8;

insert into test_innodb_lock values (1,'a');

insert into test_innodb_lock values (2,'b');

insert into test_innodb_lock values (3,'c');

insert into test_innodb_lock values (4,'d');

insert into test_innodb_lock values (5,'e');

创建索引

create index idx_lock_a on test_innodb_lock(a);

create index idx_lock_b on test_innodb_lock(b);

MySQL 各种锁演示

先将自动提交事务改成手动提交:set autocommit=0;

我们启动两个会话窗口 A 和 B,模拟一个抢到锁,一个没抢到被阻塞住了。

行锁(写&读)

A 窗口执行

update test_innodb_lock set b='a1' where a=1;

SELECT * from test_innodb_lock;

我们可以看到 A 窗口可以看到更新后的结果

B 窗口执行

SELECT * from test_innodb_lock;

我们可以看到 B 窗口不能看到更新后的结果,看到的还是老数据,这是因为 a = 1 的这行记录被 A 窗口执行的 SQL 语句抢到了锁,并且没有执行 commit 提交操作。所以窗口 B 看到的还是老数据。这就是 MySQL 隔离级别中的"读已提交"。

窗口 A 执行 commit 操作

COMMIT;

窗口 B 查询

SELECT * from test_innodb_lock;

这个时候我们发现窗口 B 已经读取到最新数据了

行锁(写&写)

窗口 A 执行更新 a = 1 的记录

update test_innodb_lock set b='a2' where a=1;

这时候并没有 commit 提交,锁是窗口 A 持有。

窗口 B 也执行更新 a = 1 的记录

update test_innodb_lock set b='a3' where a=1;

可以看到,窗口 B 一直处于阻塞状态,因为窗口 A 还没有执行 commit,还持有锁。窗口 B 抢不到 a = 1 这行记录的锁,所以一直阻塞等待。

窗口 A 执行 commit 操作

COMMIT;

窗口 B 的变化

可以看到这个时候窗口 B 已经执行成功了

表锁

当索引失效的时候,行锁会升级成表锁,索引失效的其中一个方法是对索引自动 or 手动的换型。a 字段本身是 integer,我们加上引号,就变成了 String,这个时候索引就会失效了。

窗口 A 更新 a = 1 的记录

update test_innodb_lock set b='a4' where a=1 or a=2;

窗口 B 更新 a = 2 的记录

update test_innodb_lock set b='b1' where a=3;

这个时候发现,虽然窗口 A 和 B 更新的行不一样,但是窗口 B 还是被阻塞住了,就是因为窗口 A 的索引失效,导致行锁升级成了表锁,把整个表锁住了,索引窗口 B 被阻塞了。

窗口 A 执行 commit 操作

COMMIT;

窗口 B 的变化

可以看到这个时候窗口 B 已经执行成功了

间隙锁

什么是间隙锁

当我们采用范围条件查询数据时,InnoDB 会对这个范围内的数据进行加锁。比如有 id 为:1、3、5、7 的 4 条数据,我们查找 1-7 范围的数据。那么 1-7 都会被加上锁。2、4、6 也在 1-7 的范围中,但是不存在这些数据记录,这些 2、4、6 就被称为间隙。

间隙锁的危害

范围查找时,会把整个范围的数据全部锁定住,即便这个范围内不存在的一些数据,也会被无辜的锁定住,比如我要在 1、3、5、7 中插入 2,这个时候 1-7 都被锁定住了,根本无法插入 2。在某些场景下会对性能产生很大的影响

间隙锁演示

我们先把字段 a 的值修改成 1、3、5、7、9

窗口 A 更新 a = 1~7 范围的数据

update test_innodb_lock set b='b5' where a>1 and a<7;

窗口 B 在 a = 2 的位置插入数据

insert into test_innodb_lock values(2, "b6");

这个时候发现窗口 B 更新 a = 2 的操作一直在等待,因为 1~7 范围的数据被间隙锁,锁住了。只有等窗口 A 执行 commit,窗口 B 的 a = 2 才能更新成功

行锁分析

执行 SQL 分析命令

show status like 'innodb_row_lock%';

Variable_name 说明

Innodb_row_lock_current_waits:当前正在等待锁定的数量。

Innodb_row_lock_time:从系统启动到现在锁定的时长。

Innodb_row_lock_time_avg:每次等待锁所花平均时间。

Innodb_row_lock_time_max:从系统启动到现在锁等待最长的一次所花的时间。

Innodb_row_lock_waits:系统启动后到现在总共等待锁的次数。

最后

感谢大家看到这里,文章有不足,欢迎大家指出;如果你觉得写得不错,那就给我一个赞吧。

mysql某个表被行锁了_一文搞懂MySQL行锁、表锁、间隙锁详解相关推荐

  1. JAVA秒杀mysql层实现_一文搞懂MySQL的Join,聊一聊秒杀架构设计

    正文 MySQL的Join到底能不能用 经常听到2种观点: join性能低,尽量少用 多表join时,变为多个SQL进行多次查询 其实对于上面的观点一定程度上是正确的,但不是完全正确.但之所以流传这么 ...

  2. 一文搞懂MySQL数据库分库分表

    如果数据量过大,大家一般会分库分表.分库需要注意的内容比较少,但分表需要注意的内容就多了. 工作这几年没遇过数据量特别大的业务,那些过亿的数据,因为索引设置合理,单表性能没有影响,所以实战中一直没用过 ...

  3. 一文搞懂 MySQL 索引

    一文搞懂 MySQL 索引 1.MySQL 索引 简介 1.1.MySQL 索引 是什么?  索引是一个单独的.存储在 磁盘 上的 数据库结构 ,包含着对数据表里 所有记录的 引用指针. 1.2. M ...

  4. 一文搞懂MySQL XA如何实现分布式事务

    一文搞懂MySQL XA如何实现分布式事务 前言 XA 协议 如何通过MySQL XA实现分布式事务 前言 MySQL支持单机事务的良好表现毋庸置疑,那么在分布式系统中,涉及多个节点,MySQL又是如 ...

  5. mysql删除分表键_一文看懂 MySQL 分区和分表,提高表增删改查效率

    原标题:一文看懂 MySQL 分区和分表,提高表增删改查效率 作者:冯帅,精通Oracle. MySQL. 擅长异构数据库数据同步及迁移.数据库的设计和调优,对高可用方案有深入研究. MySQL分区和 ...

  6. mysql 默认事务隔离级别_一文读懂MySQL的事务隔离级别及MVCC机制

    回顾前文: <一文学会MySQL的explain工具> <一文读懂MySQL的索引结构及查询优化> (同时再次强调,这几篇关于MySQL的探究都是基于5.7版本,相关总结与结论 ...

  7. python语言语句快的标记是什么_一文搞懂Python程序语句

    原标题:一文搞懂Python程序语句 程序流 Python 程序中常用的基本数据类型,包括: 内置的数值数据类型 Tuple 容器类型 String 容器类型 List 容器类型 自然的顺序是从页面或 ...

  8. 面试让HR都能听懂的MySQL锁机制,欢声笑语中搞懂MySQL锁

    腾讯云数据库负责人林晓斌说过:"我们面试MySQL同事时只考察两点,索引和锁".言简意赅,MySQL锁的重要性不言而喻. 本文通过同事"侨总"的一场面试,带你通 ...

  9. 一文搞懂 mysql 中的共享锁、排他锁、悲观锁、乐观锁及使用场景

    目录 一.常见锁类型 二.Mysql引擎介绍 三.常用引擎间的区别 四.共享锁与排他锁 五.排他锁的实际应用 六.共享锁的实际应用 七.死锁的发生 八.另一种发生死锁的情景 九.死锁的解决方式 十.意 ...

最新文章

  1. 修改Java-source版本
  2. 【原创】二级指针中在内存中的样子
  3. DGL教程【三】构建自己的GNN模块
  4. Django(part7)--请求及HttpRequest对象
  5. spring定时器,定时器一次执行两次的问题
  6. 解决 VUE前端项目报错:RangeError: Maximum call stack size exceeded
  7. linux ssh密钥登录配置
  8. android 之反编译
  9. 错误 Cannot load driver class: com.mysql.jdbc.Driver
  10. Kali Linux 软件源和软件更新(留着自己看)
  11. C++/Qt获取屏幕尺寸和放大比例
  12. iOS远程真机之iTunes与iPhone的通信协议usbmuxd解析
  13. Fluent compiled 失败
  14. PHP版本升级了旧代码怎么办?编程语言PHP还有未来吗?[图]
  15. Linux下如何拷贝隐藏文件
  16. iOS第三方直播的集成
  17. window 2003安装完系统之后网卡驱动处理办法
  18. 巧用书法字帖提高书法造诣
  19. 团战可以输 提莫必须死
  20. Android中am命令用法

热门文章

  1. 码农们的聚餐,会复杂到什么程度?
  2. Dubbo 沉睡,Spring Cloud 崛起!
  3. 区块链爆史诗级漏洞,可完全控制虚拟货币交易!
  4. B站在美上市 A站却为融资心塞
  5. 继去年“技惊四座”之后,腾讯TPG图片格式在应用领域有了新进展
  6. Uber “杀人”事件
  7. 和阿里同年创办,为何当当却走向了“卖身”的结局?
  8. iOS 11.3 显示:Apple ID 或将实现微信式扫码登陆
  9. 一文了解 Java 应用程序性能优化指南
  10. 用Python搭建“冲顶大会”外挂,王思聪们还舍得撒币吗?