mysql锁的种类

  • 行级锁: 有两种: 共享锁和排他锁,
  • 表级别锁: 两种意向锁:共享 & 排他
  • 特殊锁: 插入意向锁:属于行锁

行锁和表锁的转化

  • 行锁必须有索引才能实现, 如果sql中没有索引就走表锁

行锁算法

  • recore lock:记录锁: 通过主键和唯一索引对数据行操作时, 会对该数据加上记录锁
  • gap lock:间隙锁: 基于非唯一索引, 锁定一段范围的记录。——解决幻读问题
  • next-key lock: 锁定范围+记录本身——-
  • 重点: 行锁默认是next-key锁, 遇到特殊情况会退化成间隙锁或者行锁

意向锁

https://juejin.cn/post/6844903666332368909

  • 解决的问题: innobe允许表锁和行锁同时存在, 为了给表加排他锁时, 就不需要遍历每一行检测是否已经加了排他锁, 就只需要有无意向排他锁即可。

插入意向锁

https://juejin.cn/post/6844903666856493064—-是一种特殊的间隙锁, 为了解决并发插入的问题,

经典问题

  • for update: 悲观锁, 会加上排他锁, 其他事物可以读取但是不能更新

死锁日志分析

locks rec bu not gap代表锁住是以恶索引, 不是一个范围

实战

  • 实战1

https://cloud.tencent.com/developer/article/1801978

CREATE TABLE student ( id int(11) NOT NULL AUTO_INCREMENT COMMENT ‘自增主键’, name varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT ‘名称’, age int(3) NOT NULL COMMENT ‘年龄’, school varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL COMMENT ‘学校’, PRIMARY KEY (id) USING BTREE, UNIQUE INDEX name_age(name, age) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_bin ROW_FORMAT = Compact;

insert student(name, age, school) values(“test1”, 10, “value1”); insert student(name, age, school) values(“test10”, 10, “value2”);

image.png

  • 实战二

    1. [https://segmentfault.com/a/1190000019745324](https://segmentfault.com/a/1190000019745324)

https://km.woa.com/articles/show/423783?from=iSearch
https://km.woa.com/group/46654/articles/show/445662?from=iSearch
https://km.woa.com/group/39561/articles/show/474514?from=iSearch#%E5%85%B1%E4%BA%AB%E9%94%81%E5%92%8C%E6%8E%92%E4%BB%96%E9%94%81

疑问

1: 怎么查看是行锁还是表锁?
2: 怎么验证一些结论通过mysql的锁表信息

学习总结

1: 多实战 而不是停留在看文档阶段, 可以多构造几个异常, 比如锁等待, 死锁等场景,自己分析自己玩
2: 多关注码客上mysql的标签
3: 提单给dba一起探讨
4: 通过ppt或者其他方式总结提炼
5: 遇到问题多猜测, 多验证才是王道, 而不是无脑搜答案

经典问题分析:

我们业务在执行 delete from t_dynamic_topic_info where id in(select id from t_topic_info where status=2) 时发现 t_topic_info这张表也被锁定了 我在网上找了文章 说里面的解释时 update下的子查询 如果没有索引,会导致锁表。https://blog.csdn.net/anzhen0429/article/details/80944614 但是这个和我们的例子不太一样,而且这个网站说的锁升级时主查询的表锁升级,好像没办法解释我们业务这个 t_topic_info为啥被锁表?
希望mysql大佬帮忙解答一下,谢谢~
ps:
t_topic_info 有没有加锁不确定,有没有可能时执行t_dynamic_topic_info的删除操作很慢影响了 t_topic_info 的update? mysql可以同时对不同的表写的吧? 可以对在被in()的表进行写的吗?数据库隔离级别时RC

不是表锁,是delete的子查询用的是select lock in share mode的实时读,不是mvcc快照读
这里以一个相似的表结构和数据为例
image.png
由于5.7下统计信息里锁信息展示的不太完善,这里以8.0为例(加锁方面和5.7还是差不多的)
session1
image.png
session2
image.png
会发现session的update t1被阻塞了
查看锁信息
image.png
这里 58655对应的事务就是session2,可以看出被session1对t1加的S-lock阻塞了
上面说的是rc隔离级别下,如果是rr隔离级别,由于f1上没有索引,session的delete from t2 where f1 in (select f1 from t1 where f1 = 1);会对t1的所有行加s-lock,几乎等同于表锁
image.png
image.png