MySQL 问题汇总
# 锁超时
当出现 Lock wait timeout exceeded; try restarting transaction ,可以通过以下 SQL 来排查:
查看 InnoDB 存储引擎内部状态信息的命令,它可以提供非常详细的关于 InnoDB 存储引擎的运行状态、性能指标以及当前存在的问题等信息
SHOW ENGINE INNODB STATUS;1内容包括
事物信息,锁信息,缓冲池信息,日志信息,表空间信息,当程序发生以上报错信息,使用该语句,可以查看到相关报错信息。查看当前被锁定或正在使用的表的命令。它能帮助你识别哪些表正在被事务或查询占用,从而排查锁等待、死锁等问题
SHOW OPEN TABLES WHERE In_use > 0; # 示例 +----------+-------------+--------+-------------+ | Database | Table | In_use | Name_locked | +----------+-------------+--------+-------------+ | mydb | orders | 2 | 0 | | mydb | customers | 1 | 0 | +----------+-------------+--------+-------------+ * orders 表被锁定 2 次(可能有两个并发事务在操作它)。 * customers 表被锁定 1 次。 * 两个表的名称均未被锁定(Name_locked=0),可正常进行 DML 操作。1
2
3
4
5
6
7
8
9
10
11- Database 表所在的数据库名称。
- Table 表的名称。
- In_use 表示当前正在使用的连接数。
- Name_locked 表示当前表是否被锁定。
看当前正在执行操作的线程(即非空闲连接)的 SQL 查询。它能帮助你监控数据库中活跃的查询和事务,排查性能问题或长时间运行的任务。
SELECT * FROM information_schema.PROCESSLIST WHERE Command != 'Sleep'; # 示例 +-------+------+-------------------+--------+---------+------+------------------+----------------------------------+ | ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | +-------+------+-------------------+--------+---------+------+------------------+----------------------------------+ | 12345 | root | localhost | mydb | Query | 120 | Sorting result | SELECT * FROM orders ORDER BY id | | 12346 | app | 192.168.1.1:56789 | mydb | Execute | 5 | Sending data | UPDATE users SET status=1 WHERE id=100 | +-------+------+-----------+--------+---------+------+------------------+----------------------------------+ * 线程 12345:用户 root 在执行 SELECT 查询,已运行 120 秒,正在排序结果(可能需要优化索引)。 * 线程 12346:应用用户 app 在执行 UPDATE,运行 5 秒,正在返回数据。1
2
3
4
5
6
7
8
9
10- ID 线程 ID(唯一标识),用于 KILL 命令终止线程(如 KILL 12345;)。
- USER 执行该线程的用户(如 root、app_user)。
- HOST 客户端主机名或 IP 地址(如 localhost、192.168.1.1:56789)。
- DB 当前线程操作的数据库名(若未指定则为 NULL)。
- COMMAND 线程当前执行的命令类型:・Query:正在执行 SQL 查询。・Sleep:空闲等待。・Connect:正在连接数据库。・Execute:正在执行预处理语句。
- TIME 线程已持续执行的时间(秒)。若值很大,可能是慢查询或事务未提交。
- STATE 线程当前状态(如 Sorting result、Copying to tmp table),指示查询执行到哪一步。
- INFO 正在执行的 SQL 语句(可能被截断,使用 SHOW FULL PROCESSLIST 可查看完整语句)。
SELECT * FROM information_schema.PROCESSLIST WHERE Command != 'Sleep'; 语句能方便的看到当前有哪个 sql 正在占有锁,可以看他的执行时间,如果太长,需要考虑是否优化,也可以立马 kill 这个线程,如果 kill 不起作用,需要重启 mysql。
# 行大小过大
Row size too large. The maximum row size forthe used table type, not counting BLOBs, is 8126. Thisincludes storage overhead, check the manual. You have tochange some columns to TEXT Or BLOBS.
这是因为 MyISAM 表存储引擎对行大小有限制,MyISAM 引擎的限制为 8192 字节,但需扣除「存储开销」(如字段描述、校验信息等),最终实际可用的行内长度约为 8126 字节;
InnoDB 存储引擎的限制为 65535 字节(同样需扣除存储开销,但实际可用接近此值);
所谓行大小限制,就是你给字段设置的大小,比如 a 字段为 varchar (30), 那么他就占总行的 30 字节,所有字段所占字节的总和超过限制则会报错。
这种情况可以给某些字段设置 TEXT 或 BLOB,这样这些字段的数据将不再保存在行中,而是保存在数据库中,行大小将不会受限制,也就是若数据较短 (<768 字节在行内),若数据较长 (>768 字节在行外,即行内存的是指针占 20 个字节),