生产环境避坑:哪些 SQL 操作会导致数据库宕机
做后端或者运维的,最怕半夜接到报警电话说数据库扛不住了。很多时候,问题就出在一行看似无害的 SQL 上。今天复盘几个典型的'杀手级'写法,大家写代码时多留个心眼。
没加索引的全表扫描
最基础的错误,但杀伤力最大。比如查一个大表:
SELECT * FROM large_table WHERE unindexed_column = 'value';
如果 unindexed_column 没建索引,数据库就得把整张表扫一遍。数据量一大,I/O 瞬间打满,CPU 飙升,服务自然响应变慢甚至挂掉。
关联查询缺索引
多表 Join 的时候,关联字段没索引也是灾难。这时候数据库可能被迫用嵌套循环(Nested Loop),复杂度直接爆炸。
SELECT * FROM table_a JOIN table_b ON table_a.unindexed_id = table_b.unindexed_id;
大事务与批量操作
单事务里塞太多事,锁住资源不放,日志文件也能撑爆。别小看这种一次性提交的操作:
BEGIN;
INSERT INTO log_table SELECT * FROM huge_source_table;
UPDATE statistics SET count = count + 1000000;
COMMIT;
还有那种一次性删几十万条会话记录的操作,不分批处理,锁等待队列能排到天际。
DELETE FROM session_table WHERE expire_time < NOW();
逻辑漏洞引发的死循环
有时候不是资源不够,是逻辑错了。比如忘了写连接条件,直接搞出笛卡尔积,结果集行数相乘,内存瞬间溢出。
SELECT * FROM users, orders;
再比如递归 CTE 没设终止条件,无限递归下去,进程直接卡死。
WITH infinite_loop ( n n infinite_loop ) infinite_loop;

