朕的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();
至此,顺序执行这件“小”事,就成了你手里听话的锦衣卫:指哪打哪,绝不自作主张。
nat123映射怎么用?超详细步骤,外网访问内网轻松搞定
nat123域名怎么用?两种方式轻松搞定
nat123怎么用?简单几步实现内网穿透
内网穿透工具对比:nat123、花生壳与轻量新选择
远程访问内网很简单:用对工具,一“箭”穿透
ngrok下载完全指南:从入门到获取客户端
内网远程桌面软件:穿透局域网边界的数字窗口
从外网远程访问内网服务器的完整方案
Windows Server 2008端口转发完全教程:netsh命令添加/查看/删除/重置
为什么三层交换机转发比Linux服务器快?转发表硬件加速的秘密