笔记 笔记
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

EasT-Duan

Java 开发
首页
  • 开发工具
  • Java Web
  • Java 进阶
  • 容器化技术
  • Java 专栏

    • Java 核心技术面试精讲
    • Java 业务开发常见错误 100 例
  • 数据库专栏

    • MySQL 实战 45 讲
    • Redis 核心技术与实战
  • 安全专栏

    • OAuth 2.0 实战课
  • 计算机系统
  • 程序设计语言
  • 数据结构
  • 知识产权
  • 数据库
  • 面向对象
  • UML
  • 设计模式
  • 操作系统
  • 结构化开发
  • 软件工程
  • 计算机网络
  • 上午题错题
在线工具 (opens new window)

购买兑换码请添加

添加时候请写好备注,否则无法通过。

  • 19-为什么我只查一行的语句,也执行这么慢?

    • 等行锁
      • 查询慢
      EasT-Duan
      2024-03-15
      随笔
      目录

      19-为什么我只查一行的语句,也执行这么慢?

      欢迎来到我的 ChatGPT 中转站,极具性价比,为付费不方便的朋友提供便利,有需求的可以添加左侧 QQ 二维码,另外,邀请新用户能获取余额哦!最后说一句,那啥:请自觉遵守《生成式人工智能服务管理暂行办法》。

      正文

      # 等行锁

      Session A Session B
      begin;
      update t set c = c+1 where id = 1;
      select * from t where id = 1 lock in share mode;(lock in share mode 等价于 for update,第 8 篇讲过)

      执行完成后发现 Session B 被阻塞。执行下面命令可以看到阻塞。

      select * from sys.innodb_lock_waits where locked_table='`test`.`t`'\G
      
      1

      这里能看到造成阻塞的是 103 号线程,执行 KILL QUERY 103 或者 QUERY 103。但是执行 KILL QUERY 103 是没有用的,这个语句是代表停止执 103 号线程正在执行的语句,而造成阻塞的是 for update 行锁语句。必须执行 QUERY 103 才行,断开链接,就自动回滚了事务的执行的语句了。

      # 查询慢

      select * from t where c=50000 limit 1; 
      
      1

      因为 C 没有索引,这个会扫描 50000 行才会返回。但是通过慢查询日志却发现并不是很慢,所以印证了一句话:坏查询不一定是慢查询。10 万行看着不慢,等数据量上去后就线性涨上去了。

      再看一个案例

      select * from t where id = 1;
      ## 但是这个查询却非常快。
      select * from t where id = 1  for update ;
      
      1
      2
      3

      image-20240314193411078image-20240314194332330

      复现步骤

      SessionA SessionB
      start transaction with consistent snapshot
      update t set c = c+1 where id =1 ; /100 万次 /
      select * from t where id = 1;
      select * from t where id = 1 for update / lock in share mode ;

      这是因为用了一致性读取,undo log 会创建出来 100 万个回滚日志, select * from t where id = 1; 要找到创建快照时候对应的那条数据,而 select * from t where id = 1 for update / lock in share mode ; 是当前读,所以就能立刻找到。

      #MySQL
      上次更新: 2025/04/12, 05:37:39
      最近更新
      01
      Reactor 核心
      02-24
      02
      前置条件
      10-30
      03
      计算机网络
      09-13
      更多文章>
      Theme by Vdoing | Copyright © 2019-2025 powered by Vdoing
      • 跟随系统
      • 浅色模式
      • 深色模式
      • 阅读模式