看到 ERROR 1064
或类似语法错误,先检查 SQL 是否被意外截断或换行符损坏
MySQL 报错以
ERROR 1064开头,基本可锁定为语法问题,但真正原因常不是“写错了关键字”,而是客户端或应用层传入了不完整的 SQL。比如 PHP 中用
mysqli_real_escape_string()处理后拼接字符串,若原始数据含未闭合的单引号,会导致后续语句被截断;又或者 Python 的
cursor.execute()传入多行字符串时,Windows 换行符
\r\n在某些驱动中引发解析异常。 在 MySQL 客户端里直接
SELECT出你实际执行的完整 SQL 字符串(比如从慢日志、general_log 或应用日志中复制),粘贴进
mysql -e "..."手动执行,看是否复现 用
HEX()查看字段值:如
SELECT HEX(content) FROM logs WHERE id = 123;,确认是否有不可见字符(如
0x00、
0xA0)混入 避免在应用中拼接 SQL,优先使用预处理语句(
PREPARE/
EXECUTE或各语言对应的参数化查询)
查询突然变慢且无报错,重点查执行计划是否走了全表扫描
没报错不等于没问题。常见现象是某条
SELECT延迟从几毫秒涨到数秒,但返回仍是 200 和正确结果。这时
EXPLAIN是第一响应工具,但要注意它只反映“当前优化器选择”,不代表真实执行路径。 对慢查询加
EXPLAIN FORMAT=JSON,重点关注
key是否为
NULL、
rows是否远超预期、
type是否为
ALL或
index确认 WHERE 条件字段是否有可用索引:比如查询
WHERE status = 'active' AND created_at > '2024-01-01',但只有
status单列索引,
created_at索引未被合并使用 注意隐式类型转换:如
WHERE user_id = '123'(
user_id是
INT),MySQL 会放弃索引走全表扫描;改用
WHERE user_id = 123即可恢复
Lock wait timeout exceeded
错误本质是事务卡住,不是锁本身有问题
ERROR 1205 (HY000): Deadlock found when trying to get lock和
ERROR 1205 (HY000): Lock wait timeout exceeded都指向锁等待,但成因不同。前者是死锁,MySQL 自动回滚一方;后者是等待超时(默认
innodb_lock_wait_timeout=50秒),说明有长事务或未提交操作占着资源。 立刻查
SELECT * FROM information_schema.INNODB_TRX;,看
TRX_STATE是否为
LOCK WAIT,再比对
TRX_STARTED时间,找出运行过久的事务 结合
information_schema.INNODB_LOCK_WAITS和
INNODB_LOCKS(MySQL 5.7+ 已废弃,8.0+ 用
performance_schema.data_locks)定位阻塞源头 应用层必须显式控制事务边界:避免在事务内做 HTTP 调用、文件读写等外部耗时操作;所有
BEGIN必须配对
COMMIT或
ROLLBACK
连接数打满报 Too many connections
时,别急着调大 max_connections
这个错误表面是连接不够,实则大概率暴露应用层连接泄漏或短连接滥用。盲目调高
max_connections只会让问题延后爆发,还可能压垮服务器内存。 先执行
SHOW STATUS LIKE 'Threads_connected';看实时连接数,再对比
SHOW VARIABLES LIKE 'max_connections';,确认是否真接近上限 查
SHOW PROCESSLIST;,过滤掉
Command = 'Sleep'且
Time值很大的连接,这些通常是应用未正确 close 的连接 检查应用是否用了连接池:如 Java 的 HikariCP 应设
maxLifetime和
idleTimeout;PHP 的 PDO 默认不复用连接,需显式启用
PDO::ATTR_PERSISTENT
排查 MySQL 查询异常,最易忽略的是「错误不在 SQL 本身,而在它被构造、传输、执行的上下文里」——比如字符集不一致导致条件匹配失败,或主从延迟让读请求拿到旧数据而误判为查询出错。动手前,先确认你看到的“异常”,到底是数据库报的错,还是应用逻辑认为它错了。
