当前位置: 首页 > news >正文

MySQL - 全表扫描 会发生死锁?

MySQL全表扫描与死锁的关系分析:全表扫描本身不会直接导致死锁,但在特定场景下可能间接参与死锁形成。在InnoDB引擎中,不同隔离级别下全表扫描的加锁机制不同,而MyISAM引擎会加表级读锁。死锁发生的四个必要条件包括互斥访问、持有并等待等。全表扫描可能通过并发更新、索引扫描顺序不一致或锁升级冲突等场景间接引发死锁。为避免此类问题,建议优化查询、控制事务大小、统一访问顺序等。通过合理设计索引和访问路径,可有效预防死锁发生。

MySQL 全表扫描与死锁的关系

全表扫描本身​​不会直接导致死锁​​,但在特定场景下可能​​间接参与死锁的形成​​。

以下是详细分析:

一、全表扫描的锁机制

1. InnoDB 引擎

  • ​不加锁​​:在 READ COMMITTEDREAD UNCOMMITTED 隔离级别下,普通 SELECT 全表扫描​​不加任何锁​
  • ​加共享锁​​:在 REPEATABLE READSERIALIZABLE 隔离级别下:
    SELECT * FROM table FOR SHARE; -- 显式加共享锁
    SELECT * FROM table LOCK IN SHARE MODE; -- 旧语法
    会逐行加共享锁(S锁)

2. MyISAM 引擎

  • ​表级锁​​:全表扫描会自动加​​读锁​​,阻塞所有写入操作

二、死锁发生的必要条件

死锁需要同时满足以下条件:

  1. ​互斥访问​​:资源不能共享
  2. ​持有并等待​​:进程持有资源同时请求新资源
  3. ​不可剥夺​​:资源只能自愿释放
  4. ​循环等待​​:多个进程形成等待环

三、全表扫描参与死锁的场景

场景1:全表扫描 + 并发更新(InnoDB)

-- 事务A
START TRANSACTION;
SELECT * FROM users WHERE age < 18 FOR UPDATE; -- 全表扫描加排他锁-- 事务B
START TRANSACTION;
UPDATE users SET status=1 WHERE id=5; -- 请求单行锁

若事务A先锁定了id=5的行,事务B被阻塞;同时事务A后续扫描到其他行时可能被事务B已锁定的行阻塞,形成循环等待。

场景2:索引扫描顺序不一致

-- 事务A (使用索引)
UPDATE products SET stock=stock-1 WHERE category='electronics';-- 事务B (全表扫描)
UPDATE products SET price=price*1.1 WHERE discount > 0.5;

两个事务加锁顺序不同(索引顺序 vs 物理顺序),可能导致交叉死锁。

场景3:锁升级冲突

-- 事务A
SELECT COUNT(*) FROM orders; -- 全表扫描(MyISAM表)-- 事务B
INSERT INTO orders (...) VALUES (...); -- 等待读锁释放

在MyISAM中,长时间的全表扫描会阻塞所有写入操作,但不会直接导致死锁(因为没有循环等待)。

四、为什么全表扫描很少直接导致死锁?

  1. ​扫描过程不加锁​​:InnoDB 普通 SELECT 在低隔离级别不加锁
  2. ​锁粒度控制​​:InnoDB 是逐行加锁,而非一次性锁全表
  3. ​死锁检测机制​​:InnoDB 会自动检测并回滚其中一个事务
    SHOW ENGINE INNODB STATUS; -- 查看最近死锁信息

五、避免全表扫描死锁的最佳实践

  1. ​优化查询​​:

    -- 添加合适索引
    ALTER TABLE users ADD INDEX idx_age (age);
  2. ​控制事务大小​​:

    -- 分批处理
    DELETE FROM logs WHERE created_at < '2020-01-01' LIMIT 1000;
  3. ​统一访问顺序​​:

    // 程序代码中固定操作顺序
    $tables = ['customers', 'orders'];
    sort($tables); // 确保所有事务按相同顺序访问表
  4. ​降低隔离级别​​:

    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
  5. ​设置锁等待超时​​:

    SET innodb_lock_wait_timeout = 30; -- 单位:秒

六、诊断工具

  1. 查看当前锁:

    SELECT * FROM performance_schema.data_locks;
  2. 死锁日志:

    SHOW ENGINE INNODB STATUS\G
  3. 监控长时间扫描:

    SELECT * FROM sys.session WHERE sql_text LIKE '%SELECT%';

-- 死锁日志

SHOW ENGINE INNODB STATUS\G

结论

全表扫描​​本身不会直接导致死锁​​,但在以下情况可能参与死锁链:

  • 显式加锁(FOR UPDATE/LOCK IN SHARE MODE
  • 与更新操作混合执行
  • 不同事务使用不同的访问路径

通过合理设计索引、控制事务大小和统一访问顺序,可有效避免此类死锁。


文章转载自:

http://yKMFO8zy.Ltrms.cn
http://mf5GQQGw.Ltrms.cn
http://Sh0SDokt.Ltrms.cn
http://b6FyVTrh.Ltrms.cn
http://sfqgUGi7.Ltrms.cn
http://NaDI3h59.Ltrms.cn
http://FE7CtpvV.Ltrms.cn
http://LDkCQk7K.Ltrms.cn
http://5hWQdMFi.Ltrms.cn
http://GmbuLO1e.Ltrms.cn
http://7wOG25J9.Ltrms.cn
http://VF5Pda6q.Ltrms.cn
http://NRy0hOsK.Ltrms.cn
http://Pnr3zO9h.Ltrms.cn
http://ceUiWqRG.Ltrms.cn
http://NNaHVpE8.Ltrms.cn
http://N2pW8Gkj.Ltrms.cn
http://qDxiCIix.Ltrms.cn
http://WwxvHdYH.Ltrms.cn
http://X9Tu3z7E.Ltrms.cn
http://T1spLI3N.Ltrms.cn
http://z7rp7hvg.Ltrms.cn
http://7pbRR0HP.Ltrms.cn
http://Ohw1yOIv.Ltrms.cn
http://ZwMrXWH8.Ltrms.cn
http://B7A88ZUt.Ltrms.cn
http://ZKxIlAH2.Ltrms.cn
http://kybsor5A.Ltrms.cn
http://3HbRvdaA.Ltrms.cn
http://WpfMM0xr.Ltrms.cn
http://www.dtcms.com/a/376970.html

相关文章:

  • 0代码,教你三步搭建AI Agent
  • Flask 前后端分离架构实现支付宝电脑网站支付功能
  • Next.js 客户端渲染 (CSR) 与 Next.js 的结合使用
  • GitHub 镜像站点
  • S7-200 SMART 实战:自动包装控制系统的指令应用拆解(程序部分)
  • 从音频到Token:构建原神角色语音识别模型的完整实践
  • 【从0开始学习Java | 第16篇】数据结构 -树
  • (设计模式)区分建造者、 规格模式(MyBatis Example+Criteria )
  • Shell 条件测试与 if 语句:从基础到实战
  • 数据结构 之 【布隆过滤器 的简介】
  • 《sklearn机器学习——数据预处理》归一化
  • 网络编程(7)
  • 嘉立创EDA从原理图框选住器件进行PCB布局
  • 浅谈代理流程自动化 (APA)
  • 图论3 图的遍历
  • MySQL内核革新:智能拦截全表扫描,百度智能云守护数据库性能与安全
  • 从0°到180°,STM32玩转MG996R舵机
  • Openresty Tracing 最佳实践
  • 少儿舞蹈小程序(12)作品列表查询搭建
  • 机器学习投票分类
  • Python Web工程之Flask项目中添加健康检查
  • javaEE-Spring IOCDI
  • 《常见关键字知识整理》
  • C++中的单例模式的实现
  • 淘宝闪购基于FlinkPaimon的Lakehouse生产实践:从实时数仓到湖仓一体化的演进之路
  • 云手机怎样进行自动化运行?
  • FPGA入门-状态机
  • 【Python Tkinter 】图形用户界面(GUI)开发及打包EXE指南
  • 工作效率翻倍!Excel多文件合并工具
  • 【Pywinauto库】8.4 pywinauto.timings模块