0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何排查和解决MySQL死锁问题

马哥Linux运维 来源:马哥Linux运维 2026-05-06 11:18 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

生产环境 MySQL 死锁:定位思路与根治方案

MySQL死锁是数据库运维和后端开发中最棘手的问题之一。与普通查询超时不同,死锁意味着两个或多个事务相互持有对方需要的锁,形成循环依赖,导致涉及的表或行无法被任何事务继续修改。业务系统一旦出现死锁,轻则部分请求报错,重则整个业务链路的写操作集体阻塞。

本文从死锁的形成原理出发,系统讲解如何排查、分析和解决MySQL死锁问题。内容适用于MySQL 5.7/8.0及兼容版本(MySQL 8.0在锁机制上有部分改进)。

1. 死锁的形成原理

1.1 事务与锁的基本概念

MySQL的InnoDB引擎采用行级锁(Row Lock)实现并发控制。事务在对某行数据进行修改时,会对该行加锁,直到事务提交(COMMIT)或回滚(ROLLBACK)时才释放锁。

-- 事务A:先锁定id=1的行
BEGIN;
SELECT*FROMaccountsWHEREid=1FORUPDATE; -- 对id=1加排他锁
-- 此时事务A持有id=1的锁,等待事务B释放id=2的锁

-- 事务B:先锁定id=2的行
BEGIN;
SELECT*FROMaccountsWHEREid=2FORUPDATE; -- 对id=2加排他锁
-- 此时事务B持有id=2的锁,等待事务A释放id=1的锁
-- 循环等待形成:事务A等事务B,事务B等事务A → 死锁

1.2 死锁的必要条件

数据库理论中,死锁的形成必须满足以下四个条件(Carl-RoadConditions):

条件 含义 在MySQL中的体现
互斥条件 资源不能被共享 一行数据同一时刻只能被一个事务持有排他锁
持有并等待 事务持有资源的同时请求其他资源 事务A持有id=1锁,等待id=2锁
不可抢占条件 资源不能被强制释放 锁只能被持有事务显式释放,不能被其他事务抢走
循环等待条件 形成事务间的等待循环 事务A等事务B,事务B等事务A

MySQL的InnoDB引擎通过死锁检测(Deadlock Detection)来打破循环等待:当检测到死锁后,会主动回滚代价最小的事务(通常是持有最少行锁的事务),让其他事务继续执行。

1.3 锁的类型与兼容性

InnoDB的锁类型远比表面上复杂:

锁类型 模式 兼容性 说明
共享锁(S) SELECT ... LOCK IN SHARE MODE 与S锁兼容,与X锁互斥 读取时不阻止其他读
排他锁(X) SELECT ... FOR UPDATE 与S锁、X锁均互斥 写入时锁定整行
记录锁(Record Lock) 索引记录 锁定单个索引记录 最常见的行锁
间隙锁(Gap Lock) 范围查询时 锁定区间而非记录 防止幻读
Next-Key Lock 记录锁+间隙锁 锁定记录及其区间 InnoDB默认的RR隔离级别锁
意向锁(Intention Lock) 表级锁 表上的IX/IS锁 表示事务将在表上加行级锁

Next-Key Lock是死锁的高发区:当执行范围查询(如WHERE id > 10 AND id < 20)时,Next-Key Lock会锁定(10, 20)这个间隙,如果另一个事务试图插入这个范围内的记录,会被阻塞,长期积累可能导致死锁。

-- 事务A:锁定id > 10的所有行(实际锁定区间10到正无穷)
BEGIN;
SELECT*FROMordersWHEREuser_id >100FORUPDATE;
-- Next-Key Lock锁定区间 (100, +∞)

-- 事务B:插入id=101的新订单(尝试获取插入意向锁)
BEGIN;
INSERTINTOorders (id, user_id, amount)VALUES(NULL,101,100);
-- 被事务A的Next-Key Lock阻塞:Gap Lock冲突

-- 事务A再执行:插入id=102的新订单
INSERTINTOorders (id, user_id, amount)VALUES(NULL,102,200);
-- 尝试获取插入意向锁,但事务B已经持有id=102的Gap锁
-- 死锁形成

2. 死锁的排查方法

2.1 开启死锁日志

MySQL默认将死锁信息记录到错误日志,但不会记录每次死锁的完整锁等待图。可以通过以下方式增强日志:

-- 查看当前死锁日志配置
SHOWVARIABLESLIKE'innodb_print_all_deadlocks'; -- 默认OFF

-- 开启所有死锁信息输出到错误日志(需要SUPER权限)
SETGLOBALinnodb_print_all_deadlocks =ON;

-- 查看死锁日志(MySQL错误日志文件)
-- Linux: /var/log/mysql/error.log
-- macOS Homebrew: /usr/local/var/mysql/{hostname}.err
-- Windows: {数据目录}mysql*.err

innodb_print_all_deadlocks = ON会将每次死锁的完整信息输出到错误日志,包括涉及的事务、SQL语句、持有的锁和等待的锁。

2.2 使用information_schema获取锁信息

-- 查看当前所有事务持有的锁
SELECT
  t.trx_id,
  t.trx_state,
  t.trx_started,
  t.trx_rows_locked,
  t.trx_query,
  l.lock_id,
  l.lock_mode,
  l.lock_type,
  l.lock_table,
  l.lock_index,
  l.lock_space,
  l.lock_page,
  l.lock_rec,
  l.lock_data
FROMinformation_schema.INNODB_TRX t
JOINinformation_schema.INNODB_LOCKS lONt.trx_id = l.lock_trx_id
ORDERBYt.trx_started;

-- 查看锁等待关系
SELECT
  requesting_trx.trx_idASrequesting_trx_id,
  requesting_trx.trx_queryASrequesting_query,
  blocking_trx.trx_idASblocking_trx_id,
  blocking_trx.trx_queryASblocking_query,
  blocking_locks.lock_idASblocking_lock_id,
  blocking_locks.lock_modeASblocking_lock_mode,
  blocking_locks.lock_typeASblocking_lock_type,
  blocking_locks.lock_tableASblocking_lock_table
FROMinformation_schema.INNODB_LOCK_WAITS lw
JOINinformation_schema.INNODB_TRX requesting_trxONlw.requesting_trx_id = requesting_trx.trx_id
JOINinformation_schema.INNODB_TRX blocking_trxONlw.blocking_trx_id = blocking_trx.trx_id
JOINinformation_schema.INNODB_LOCKS blocking_locksONlw.blocking_lock_id = blocking_locks.lock_id;

2.3 使用performance_schema监控锁事件

MySQL 8.0引入了更强大的performance_schema锁监控:

-- 开启锁监控(需要重启或重新配置)
UPDATEperformance_schema.setup_instruments
SETENABLED ='YES', TIMED ='YES'
WHERENAMELIKE'wait/lock%';

UPDATEperformance_schema.setup_consumers
SETENABLED ='YES'
WHERENAMELIKE'%events_transactions%';

-- 查看最近的锁等待事件
SELECT*FROMperformance_schema.events_waits_history_long
WHEREevent_nameLIKE'%lock%'
ORDERBYTIMER_ENDDESC
LIMIT20;

2.4 解读死锁日志

开启innodb_print_all_deadlocks后,错误日志会输出类似以下内容的死锁报告:

2025-04-27 1045 0x7f8c9a4c8700 INNODB MONITOR OUTPUT
========================
LATEST DETECTED DEADLOCK
------------------------
2025-04-27 1042 0x7f8c9a4c8700
*** (1) TRANSACTION:
TRANSACTION 12345, ACTIVE 5 sec inserting
mysql tablesinuse 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 99, OS thread handle 0x7f8c9a4c8700, query id 10001 localhost root updating

-- 事务1正在执行的SQL
UPDATE orders SET status ='shipped'WHERE user_id > 100

*** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 123 page no 5 n bits 200 index idx_user_id of table `shop`.`orders`
trx id 12345 lock_mode X locks rec but not gap
-- 事务1持有orders表中idx_user_id索引上的记录锁

*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 123 page no 5 n bits 200 index idx_user_id of table `shop`.`orders`
trx id 12345 lock_mode X locks rec but not gap waiting
-- 事务1正在等待另一个记录锁(可能是Gap锁冲突)

*** (2) TRANSACTION:
TRANSACTION 12346, ACTIVE 3 sec inserting
mysql tablesinuse 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 1136, 1 row lock(s)
MySQL thread id 100, OS thread handle 0x7f8c9a4c8800, query id 10002 localhost root updating

-- 事务2正在执行的SQL
INSERT INTO orders (id, user_id, amount) VALUES (NULL, 105, 299.00)

*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 123 page no 5 n bits 200 index idx_user_id of table `shop`.`orders`
trx id 12346 lock_mode X locks gap before rec
-- 事务2持有Gap锁(锁定区间)

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 123 page no 5 n bits 200 index idx_user_id of table `shop`.`orders`
trx id 12346 lock_mode X locks rec but not gap waiting
-- 事务2正在等待记录锁

-- MySQL决定回滚事务12346(较晚开始,持有锁较少)
*** WE ROLL BACK TRANSACTION 12346

关键解读点

LOCK WAIT表示当前正在等待锁

HOLDS THE LOCK(S)表示事务已持有的锁

WE ROLL BACK TRANSACTION后面是MySQL决定回滚的事务ID

lock_mode X locks rec but not gap是记录锁,不锁定间隙

lock_mode X locks gap before rec是间隙锁,锁定记录前的区间

3. 常见死锁场景与解决方案

3.1 场景一:不同事务以不同顺序访问多行

问题:事务A先锁定行1再锁定行2,事务B先锁定行2再锁定行1,形成循环等待。

解决:确保所有事务以相同顺序访问资源。

# 错误的并发写入(死锁高发)
deftransfer_funds_wrong(from_id, to_id, amount):
 withconnection.cursor()ascursor:
   # 事务1: A->B, 事务2: B->A → 死锁
    cursor.execute("SELECT balance FROM accounts WHERE id = %s FOR UPDATE", (from_id,))
    cursor.execute("SELECT balance FROM accounts WHERE id = %s FOR UPDATE", (to_id,))

# 正确的并发写入(顺序加锁)
deftransfer_funds_correct(from_id, to_id, amount):
 withconnection.cursor()ascursor:
   # 按ID顺序加锁,避免循环等待
    first_id, second_id = (from_id, to_id)iffrom_id < to_id else (to_id, from_id)
        cursor.execute("SELECT balance FROM accounts WHERE id = %s FOR UPDATE", (first_id,))
        cursor.execute("SELECT balance FROM accounts WHERE id = %s FOR UPDATE", (second_id,))

3.2 场景二:索引导致的间隙锁冲突

问题:范围查询或使用索引范围扫描时,Next-Key Lock锁定较宽区间,导致插入操作被阻塞。

解决

使用覆盖索引减少锁范围:覆盖索引(Covering Index)可以让查询只需扫描索引,不必回表,减少锁定的记录数。

-- 创建覆盖索引:查询只需扫描idx_user_id,无需回表锁定主键
CREATEINDEXidx_user_id_coveringONorders(user_id,status, amount);

-- 改写查询使用覆盖索引
SELECTstatus, amountFROMordersWHEREuser_id =100;

调整隔离级别:将隔离级别从REPEATABLE READ降为READ COMMITTED,可以减少Gap Lock的使用。

-- 方法1:会话级别调整
SETSESSIONTRANSACTIONISOLATIONLEVELREADCOMMITTED;

-- 方法2:配置文件永久调整(my.cnf / my.ini)
-- [mysqld]
-- transaction-isolation = READ-COMMITTED

3.3 场景三:主从延迟导致的锁等待升级

问题:主从架构中,从库应用事件存在延迟,主库上的长事务持有锁时间延长,增加死锁概率。

解决

-- 检查从库延迟
SHOWSLAVESTATUSG
-- 关注 Seconds_Behind_Master 字段

-- 优化从库应用速率
STOPSLAVE;
CHANGEMASTERTOMASTER_RETRY_COUNT =3;
STARTSLAVE;

3.4 场景四:大事务拆分

问题:单个事务中处理过多数据,持有锁的时间过长,死锁窗口扩大。

解决:将大事务拆分为小批量事务,减少单次持有的锁数量。

# 错误:单事务处理10万条记录
defbatch_update_wrong(ids):
 withconnection.cursor()ascursor:
    cursor.execute("BEGIN")
   foridinids: # 10万次循环,锁持有时间长
      cursor.execute(
       "UPDATE orders SET status = 'processed' WHERE id = %s",
        (id,)
      )
    cursor.execute("COMMIT")

# 正确:分批处理,每批500条
defbatch_update_correct(ids, batch_size=500):
 withconnection.cursor()ascursor:
   foriinrange(0, len(ids), batch_size):
      batch = ids[i:i + batch_size]
      cursor.execute("BEGIN")
      cursor.execute(
       "UPDATE orders SET status = 'processed' WHERE id IN (%s)"%
       ",".join(["%s"] * len(batch)),
        batch
      )
      cursor.execute("COMMIT")
      connection.commit() # 每批后立即释放锁

4. 代码层面的防死锁设计

4.1 应用层锁顺序控制

在应用层维护一个全局锁顺序规则:

importthreading

# 定义全局锁顺序:按资源ID排序
# 所有需要同时锁定多个资源的代码,必须按此顺序获取锁
LOCK_ORDER = {}

classAccountService:
 def__init__(self, db_connection):
    self.conn = db_connection

 deftransfer(self, from_id: int, to_id: int, amount: decimal.Decimal):
   # 按ID顺序确定加锁顺序
    first_id, second_id = sorted([from_id, to_id])

   # 获取应用层逻辑锁(防止代码层面的并发问题)
   withself._get_lock(first_id):
     withself._get_lock(second_id):
        self._do_transfer(first_id, second_id, amount)

 def_get_lock(self, account_id: int):
   """获取指定账户的应用层锁"""
   ifaccount_idnotinLOCK_ORDER:
      LOCK_ORDER[account_id] = threading.Lock()
   returnLOCK_ORDER[account_id]

4.2 锁超时机制

设置合理的锁等待超时时间,避免无限等待:

-- 查看当前锁等待超时(默认50秒)
SHOWVARIABLESLIKE'innodb_lock_wait_timeout'; -- 默认50

-- 设置锁等待超时为10秒
SETGLOBALinnodb_lock_wait_timeout =10;

-- 在应用程序中捕获锁等待超时异常
importpymysql
frompymysqlimportOperationalError

try:
 withconnection.cursor()ascursor:
    cursor.execute("SELECT ... FOR UPDATE")
exceptOperationalErrorase:
 ife.args[0] ==1205: # Lock wait timeout error
    logger.error(f"Lock wait timeout exceeded for transaction")
   raiseRetryableError("Lock timeout, should retry")frome
 raise

4.3 重试机制

锁等待超时不等同于死锁,被超时的其他事务可能已经完成。应用层应实现有限重试:

importtime
frompymysqlimportOperationalError

MAX_RETRIES =3
RETRY_DELAY =0.5# 秒

deftransfer_with_retry(from_id, to_id, amount):
 forattemptinrange(MAX_RETRIES):
   try:
     withconnection.cursor()ascursor:
        cursor.execute("BEGIN")
       # 锁定逻辑...
        cursor.execute("COMMIT")
     returnTrue
   exceptOperationalErrorase:
     ife.args[0] ==1205: # Lock wait timeout
        connection.rollback()
        logger.warning(f"Attempt{attempt +1}failed, retrying...")
        time.sleep(RETRY_DELAY * (attempt +1))
       continue
     raise
  logger.error(f"Transfer failed after{MAX_RETRIES}attempts")
 returnFalse

5. 监控与预防

5.1 持续监控指标

建议在数据库监控系统中追踪以下指标:

指标 阈值建议 告警策略
Innodb_row_lock_waits > 100/min 超过基线2倍告警
Innodb_row_lock_time_avg > 500ms 超过基线3倍告警
Threads_connected > max_connections * 0.7 接近连接上限告警
Lock_wait_timeout 出现任何 必须告警

-- 查看InnoDB行锁统计
SHOWSTATUSLIKE'Innodb_row_lock%';
-- +-------------------------------+-------+
-- | Variable_name         | Value |
-- +-------------------------------+-------+
-- | Innodb_row_lock_current_waits | 0   |
-- | Innodb_row_lock_time     | 12345 |
-- | Innodb_row_lock_time_avg   | 123  |
-- | Innodb_row_lock_time_max   | 5000 |
-- | Innodb_row_lock_waits     | 100  |
-- +-------------------------------+-------+

5.2 慢查询与死锁的关联分析

长时间运行的查询是死锁的主要诱因。定期分析慢查询日志:

# 查看慢查询配置
mysql -e"SHOW VARIABLES LIKE 'slow_query%';"
mysql -e"SHOW VARIABLES LIKE 'long_query_time';"

# 常用分析命令
mysqldumpslow -s t -t 20 /var/log/mysql/slow.log # 按时间排序top 20
mysqldumpslow -s c -t 20 /var/log/mysql/slow.log  # 按次数排序top 20

6. 排障清单

问题现象 排查步骤 解决方案
事务报错"Deadlock found" 1. 查看错误日志 2. 分析锁等待图 3. 找出循环等待的SQL 调整SQL顺序或加锁范围
Lock wait timeout exceeded 1. 检查innodb_lock_wait_timeout 2. 查看哪个事务长时间持有锁 优化长事务,拆分批次
某表频繁死锁 1. 分析该表的访问模式 2. 检查索引设计 3. 评估隔离级别 优化索引或降级隔离级别
从库延迟导致主库死锁 1.SHOW SLAVE STATUS2. 检查从库IO/SQL线程 优化从库应用或增加从库数量
批量更新时偶发死锁 1. 分析批量SQL的锁范围 2. 检查是否跨表操作 按主键顺序处理,减少锁冲突

死锁排查的核心能力在于正确解读INNODB_TRX、INNODB_LOCKS、INNODB_LOCK_WAITS三个系统表联合查询出的锁等待关系图。运维和开发人员应建立肌肉记忆:在生产环境出现死锁时,第一时间导出这三个表的数据快照,同时开启innodb_print_all_deadlocks抓取完整的死锁上下文。事后的日志分析比现场排查更有价值,因为死锁发生时相关事务可能已经回滚。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 数据库
    +关注

    关注

    7

    文章

    4086

    浏览量

    68573
  • MySQL
    +关注

    关注

    1

    文章

    932

    浏览量

    29780

原文标题:生产环境 MySQL 死锁:定位思路与根治方案

文章出处:【微信号:magedu-Linux,微信公众号:马哥Linux运维】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    死锁是什么?产生死锁的主要原因有哪些

    嵌入式系统设计师十二:进程管理③进程管理:死锁死锁概念:进程管理是操作系统的核心,但如果设计不当,就会出现死锁的问题。如果一个进程在等待一个不可能的事,则进程就死锁了。而如果一个或多个
    发表于 12-22 07:34

    RS-485 总线的死锁检测与解除

    针对RS-485 接口收发电路的特点,讨论RS-485 总线在Polling 和CSMA/CD 通信方式中死锁检测和解死锁的方法。该方法同样适用于RS-422 接口。
    发表于 05-13 16:12 21次下载

    DIN中的死锁避免和死锁恢复

    DIN中的死锁避免和死锁恢复 由于存在占用资源者申请另一个资源的情形,在DIN中由于拓扑结构本身存在环状路径,所以
    发表于 02-23 14:47 1239次阅读
    DIN中的<b class='flag-5'>死锁</b>避免和<b class='flag-5'>死锁</b>恢复

    MySQL死锁原因排查技巧详解

    在查询相关资料和咨询jameszhou后,知道了这个实际和innodb 引擎的写机制有关,innodb执行写事务操作时,实际是先取得索引中该行的行锁(即使该表上没有任何索引,那么innodb会在后台创建一个隐藏的聚集主键索引),再在缓存里写入,最后事务commit后正式写入DB中并释放锁。
    发表于 10-19 16:38 5145次阅读
    <b class='flag-5'>MySQL</b><b class='flag-5'>死锁</b>原因<b class='flag-5'>排查</b>技巧详解

    MySQL中的高级内容详解

    之前两篇文章带你了解了 MySQL 的基础语法和 MySQL 的进阶内容,那么这篇文章我们来了解一下 MySQL 中的高级内容。 其他文章: 138 张图带你 MySQL 入门 47
    的头像 发表于 03-11 16:55 2915次阅读
    <b class='flag-5'>MySQL</b>中的高级内容详解

    MySQL并发Replace into导致死锁场景简析

    在之前的文章 #issue 68021 MySQL unique check 问题中, 我们已经介绍了在 MySQL 里面, 由于唯一键的检查(unique check), 导致 MySQL 在 Read Commit 隔离级别
    的头像 发表于 06-13 10:56 2419次阅读
    <b class='flag-5'>MySQL</b>并发Replace into导致<b class='flag-5'>死锁</b>场景简析

    如何解决I2C器件死锁的问题?

    如何解决I2C器件死锁的问题? I2C总线是一种流行的串行通信协议,在许多嵌入式系统中使用。I2C可以连接多个从属设备到一个主控设备上,简化了系统设计和管理。然而,当I2C总线上的从属设备出现死锁
    的头像 发表于 09-12 11:18 4370次阅读

    Linux内核死锁lockdep功能

    死锁是指两个或多个进程因争夺资源而造成的互相等待的现象,如进程A需要资源X,进程B需要资源Y,而双方都掌握对方所需要的资源,且都不释放,这会导致死锁。 在内核开发中,时常要考虑并发设计,即使采用正确
    的头像 发表于 09-27 15:13 1609次阅读
    Linux内核<b class='flag-5'>死锁</b>lockdep功能

    死锁的产生因素

    一、死锁的概念 操作系统中的死锁是指: 如果在一个进程集合中的每个进程都在等待只能有该集合中的其它进程才能引起的事件,而无限期陷入僵持的局面称为死锁。 二、死锁的产生因素 1、系统拥有
    的头像 发表于 11-09 09:37 2493次阅读
    <b class='flag-5'>死锁</b>的产生因素

    死锁的现象及原理

    组件如何放入自己的项目里?把代码末两个Debug部分删除,在你的项目里添加下面两句代码即可使用死锁检测组件。 init_hook (); start_check (); 1. 死锁的现象以及
    的头像 发表于 11-10 16:32 1332次阅读
    <b class='flag-5'>死锁</b>的现象及原理

    死锁的现象以及原理

    前言 本文将从0到1写一个死锁检测组件。源码:deadlock_success.c 组件如何放入自己的项目里?把代码末两个Debug部分删除,在你的项目里添加下面两句代码即可使用死锁检测组件
    的头像 发表于 11-13 16:30 1338次阅读
    <b class='flag-5'>死锁</b>的现象以及原理

    java死锁产生的条件

    Java死锁是指多个线程因为互相等待对方释放资源而无法继续执行的情况。当线程处于死锁状态时,程序会无限期地等待资源,无法继续执行下去,从而导致整个系统的停滞。要理解并避免Java死锁的产生,首先需要
    的头像 发表于 12-04 13:42 1118次阅读

    mysql配置失败怎么办

    MySQL是一款广泛使用的关系型数据库管理系统,但在配置过程中可能会出现各种问题,导致配置失败。本文将详细介绍MySQL配置失败的常见原因和对应的解决方案,以帮助读者快速排查和解决问题
    的头像 发表于 12-06 11:03 4841次阅读

    浅谈MySQL常见死锁场景

    这里问题的原因是这个 table 里面只有record 2, 所以这里认真看, 死锁的时候是等待在 supremum 上的, 因为supremum 的特殊性, supremum 没有gap lock, 只有 next-key lock
    的头像 发表于 03-21 14:10 1672次阅读
    浅谈<b class='flag-5'>MySQL</b>常见<b class='flag-5'>死锁</b>场景

    MySQL磁盘空间问题的成因和排查方法

    运维工程师经常会遇到这样的场景:MySQL 服务器的磁盘空间告警,但查看数据目录时发现数据库本身并不大。大量磁盘空间被未知文件消耗。通过排查发现,二进制日志(Binary Log)是主要的磁盘空间消耗者。
    的头像 发表于 04-13 13:57 159次阅读