朕的SQL今天不想加班——顺序执行这件“小”事
mysql顺序执行

首页 2025-09-02 11:20:42

——谨以此文献给所有被“一条SQL跑一天”折磨过的倒霉蛋

诸位爱卿,早朝开始!今天咱们不讲江山社稷,只聊一条让万千程序员深夜抱头痛哭的小玩意儿:MySQL的“顺序执行”。
话说老衲当年,啊不,是“本人”当年,第一次写存储过程的时候,那叫一个意气风发。键盘噼里啪啦,仿佛键盘下藏着一个大明王朝的奏折堆。我潇洒地写下:
复制
BEGIN
    UPDATE user SET money = money - 100 WHERE id = 1;
    UPDATE user SET money = money + 100 WHERE id = 2;
END;
写完收工,泡好枸杞茶,坐等老板表扬。结果隔壁小王幽幽飘来一句:“哥,你这是顺序执行吗?万一第一条失败,第二条还跑不跑?”我一口茶喷出去三米远,枸杞差点儿变成暗器。
MySQL这家伙,平时看着人畜无害,一到“顺序执行”就化身东厂番子,步步杀机。诸位须知,顺序执行不是说“写在上面的语句先跑”那么简单,而是“一条不跑完,下一条绝不动筷子”。听起来很乖对吧?错!它乖得像个机器人,却一点不懂人情世故:前一条语句要是把表锁了,后一条就得在门外排队唱《凉凉》;前一条语句要是报错,后一条照跑不误,除非你手动喊“咔”。
于是,我学会了在每一句后面加“哨兵”:
复制
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
START TRANSACTION;
    UPDATE user SET money = money - 100 WHERE id = 1;
    UPDATE user SET money = money + 100 WHERE id = 2;
COMMIT;
这下好了,第一条要是摔了跟头,第二条立马被拽回来,大家一起回滚,谁也别想跑。就像两位大臣打架,皇上直接把奏折撕了,谁都别递了。
可新问题又来了:顺序执行虽然老实,但架不住有人插队。隔壁小王又飘过来:“哥,你这表没索引,全表扫描,顺序执行直接变‘顺序崩溃’。”我当场想把枸杞茶换成鹤顶红。
诸位,顺序执行的真相是:
  1. 语句按书写顺序依次进入执行引擎;
  2. 每条语句独占舞台,直到它唱完或报错;
  3. 事务包裹可以让多条语句“同生共死”;
  4. 没有索引的表,会让“顺序”变成“顺序地等死”。
所以,下次写SQL前,不妨先对表说一句:“兄弟,加个索引吧,别让顺序执行变成顺序加班。”

【教程:如何优雅地让MySQL顺序执行】
目标:在MySQL里确保多条语句严格按照先后顺序执行,且前一条失败时后一条不再执行。
步骤一:打开事务
START TRANSACTION;
作用:告诉MySQL“接下来的话,要么一起过,要么一起不过”。
步骤二:声明异常处理器
DECLARE EXIT HANDLER FOR SQLEXCEPTION ROLLBACK;
作用:任何语句抛出异常,立即回滚并退出当前块(存储过程、函数或匿名块)。
步骤三:按顺序写业务语句
复制
UPDATE account SET balance = balance - 100 WHERE id = 1;
UPDATE account SET balance = balance + 100 WHERE id = 2;
注意:此时MySQL会逐条执行,第一条不结束,第二条绝不开始。
步骤四:提交
COMMIT;
作用:全部语句成功则一次性生效;若中途有异常,EXIT HANDLER已触发ROLLBACK,所有更改撤销。
步骤五(可选):加索引
ALTER TABLE account ADD INDEX idx_id (id);
作用:让WHERE条件走索引,避免全表扫描拖慢“顺序执行”的节奏。
完整示例(存储过程版):
复制
DELIMITER $$
CREATE PROCEDURE transfer_money()
BEGIN
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;
        SELECT '转账失败,已回滚' AS msg;
    END;

    START TRANSACTION;
        UPDATE account SET balance = balance - 100 WHERE id = 1;
        UPDATE account SET balance = balance + 100 WHERE id = 2;
    COMMIT;
    SELECT '转账成功' AS msg;
END$$
DELIMITER ;

CALL transfer_money();
至此,顺序执行这件“小”事,就成了你手里听话的锦衣卫:指哪打哪,绝不自作主张。
MySQL连接就这么简单!本地远程、编程语言连接方法一网打尽
还在为MySQL日期计算头疼?这份加一天操作指南能解决90%问题
MySQL日志到底在哪里?Linux/Windows/macOS全平台查找方法在此
MySQL数据库管理工具全景评测:从Workbench到DBeaver的技术选型指南
MySQL密码忘了怎么办?这份重置指南能救急,Windows/Linux/Mac都适用
你的MySQL为什么经常卡死?可能是锁表在作怪!快速排查方法在此
MySQL单表卡爆怎么办?从策略到实战,一文掌握「分表」救命技巧
清空MySQL数据表千万别用错!DELETE和TRUNCATE这个区别可能导致重大事故
你的MySQL中文排序一团糟?记住这几点,轻松实现准确拼音排序!
别再混淆Hive和MySQL了!读懂它们的天壤之别,才算摸到大数据的门道