用大模型写 SQL 查询,导致数据库锁死
大模型生成的SQL为何会锁死数据库
很多新手用大模型(如ChatGPT)写SQL查询,结果发现数据库卡住、网页打不开,这就是典型的数据库锁死。
大模型不了解你的数据量和索引分布,极容易生成不带WHERE条件的UPDATE、全表扫描的SELECT,或者在一个长事务里执行多次操作,导致行锁升级为表锁、死锁或锁等待超时。
本文从运维角度,带你一步步排查与预防。
前置准备:确认你能看到数据库会话
在排查前,确保你有MySQL服务器权限(或使用宝塔面板的“数据库管理”)。
需要以下工具:
- MySQL命令行客户端(或phpMyAdmin)
- 至少PROCESS和SELECT权限
- 如果使用宝塔,直接登录后台,点击“数据库 → 管理 → 执行SQL”即可输入命令
小提示:如果没有命令行权限,也可以先通过宝塔面板查看慢查询日志,但本文以直接会话排查为主。
分步操作:找到锁死的SQL和锁等待源头
第一步:查看正在运行的线程
执行以下命令,观察State列是否为Waiting for table metadata lock或Locked:
SHOW FULL PROCESSLIST;
重点关注Info列里是否有大模型生成的夸张SQL,比如:
SELECT * FROM orders WHERE status = 'paid';
-- 如果orders表有1000万行且无索引,就会锁住大量行甚至整个表
第二步:分析事务和锁
如果发现多个线程处于Lock状态,用下面命令查看当前锁等待:
SELECT * FROM information_schema.INNODB_TRX\G
关注trx_started和trx_rows_locked,行数很大说明有长时间未提交的事务。
再用:
SHOW ENGINE INNODB STATUS\G
找到LATEST DETECTED DEADLOCK或TRANSACTIONS部分,可以看到哪个SQL在等待什么锁。
第三步:紧急处理——杀掉锁进程
如果确认某个SQL是罪魁祸首(比如执行了30分钟),可以用:
KILL 进程ID;
进程ID来自SHOW PROCESSLIST的Id列。
杀掉后数据库通常会立刻恢复响应。注意: 如果是在生产环境,请先评估影响。
避坑指南:大模型SQL的常见陷阱
- 缺失WHERE条件的UPDATE/DELETE:大模型有时会写
UPDATE table SET column = value,不带条件,直接锁全表。建议生成后立即加上WHERE 1=0测试。 - 全表扫描的SELECT:如果表很大且无索引,SELECT也会锁住大量行。用
EXPLAIN SELECT ...检查type是否为ALL。 - 长事务未提交:在代码里开启事务后,如果大模型生成了一些查询后没提交,事务会一直持有锁。可以设置
innodb_lock_wait_timeout参数,让等待超时自动回滚:
SET GLOBAL innodb_lock_wait_timeout = 10;
(单位:秒,建议30以内)
- 使用大模型时添加索引提示:让大模型生成SQL后,主动要求它加上
WHERE必要的索引条件,或者限制返回行数如LIMIT 100。
效果验证与长期预防
验证锁是否已解除
再次执行SHOW PROCESSLIST,观察State列恢复正常(如Sleep或简单的查询)。
然后执行业务功能,确认页面能正常加载。
长期预防措施
- 给常用大字段加索引:比如订单表的
status字段、用户表的email字段。 - 设置合理超时:在MySQL配置文件中(my.cnf)加入:
innodb_lock_wait_timeout = 10
max_execution_time = 30000 # 限制查询执行最大毫秒数
- 建立SQL审核流程:大模型生成的SQL先由DBA或自动化工具检查,比如用
pt-query-advisor。
如果你正在处理“用大模型写SQL查询导致数据库锁死”的现场,建议先按本文步骤杀掉锁进程,再根据避坑说明修改配置和索引,最后用验证命令确认环境正常。
以后使用大模型时,养成加LIMIT和WHERE条件的习惯,能大幅降低锁死风险。