MySQL中的死锁(deadlock)是指两个或多个事务在等待彼此释放资源,导致系统陷入僵局,无法继续执行。

自动死锁检测和回滚

MySQL的InnoDB存储引擎具有自动检测死锁并回滚某个事务的机制。InnoDB会选择回滚代价最小的事务,以解除死锁。这是默认行为。

捕获和处理死锁错误

在应用程序层面捕获死锁错误,并重试事务操作。可以通过捕获特定的错误代码(例如ER_LOCK_DEADLOCK)来实现。

import mysql.connector
from mysql.connector import errorcode

def execute_transaction():
    try:
        conn = mysql.connector.connect(user='user', password='password', host='localhost', database='test')
        cursor = conn.cursor()
        for attempt in range(3):  # 尝试重试3次
            try:
                cursor.execute("START TRANSACTION;")
                # 执行SQL操作
                cursor.execute("UPDATE table_name SET column1 = value1 WHERE condition;")
                cursor.execute("UPDATE table_name SET column2 = value2 WHERE condition;")
                conn.commit()
                break  # 如果成功则退出重试循环
            except mysql.connector.Error as err:
                if err.errno == errorcode.ER_LOCK_DEADLOCK:
                    print("Deadlock detected. Retrying...")
                    conn.rollback()
                else:
                    raise
    finally:
        cursor.close()
        conn.close()

execute_transaction()

手动解决步骤

  1. 查看表是否在使用

show open tables where in_use > 0 ;

若查询为空,表明没有表在使用。

不为空:

mysql>  show open tables where in_use > 0 ;
+----------+-------+--------+-------------+
| Database | Table | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | t     |      1 |           0 |
+----------+-------+--------+-------------+
1 row in set (0.00 sec)

2. 查看InnoDB的状态,获取当前死锁的信息

SHOW ENGINE INNODB STATUS\G

这条命令会返回大量关于InnoDB的运行状态信息,其中包括最近发生的死锁的信息。在输出中查找“LATEST DETECTED DEADLOCK”字段,查看涉及死锁的事务及其持有的锁。

3.查看数据库当前的进程,看一下有无正在执行的慢SQL记录线程。

show processlist;

这条命令会显示当前所有连接的线程状态,包括每个线程正在执行的SQL语句、线程ID等信息。

4.终止

KILL <thread_id>;

终止指定的事务,释放其持有的锁。