必须用SQLSTATE声明异常处理器,EXIT HANDLER需显式ROLLBACK并RESIGNAL,MyISAM和DDL会破坏事务边界。

不加 DECLARE HANDLER 就等于没处理异常——SQL失败后继续执行,事务不会自动回滚,调用方收不到错误,业务逻辑大概率错乱。
必须用 SQLSTATE,不能用 MySQL 错误码
MySQL 的 DECLARE HANDLER 只认 SQLSTATE 字符串(如 '23000'),写 1062 这类整数错误码会直接报语法错误。常见映射:
-
'23000':主键/唯一键冲突、外键约束失败,适合记录日志或返回友好提示 -
'22003':数值越界(如向TINYINT插入 256),需提前校验输入 -
'22012':除零、NULL参与算术运算,应加IF ... IS NULL或设默认值
别只写 DECLARE EXIT HANDLER FOR SQLEXCEPTION 做兜底——它会掩盖具体原因,无法区分可重试冲突和不可恢复错误。
EXIT 和 CONTINUE handler 行为差异极大
选错类型会让事务控制完全失效:
-
DECLARE EXIT HANDLER:触发后立即退出当前BEGIN...END块,适合包裹在START TRANSACTION内,天然防止“部分提交” -
DECLARE CONTINUE HANDLER:捕获后继续执行 handler 后面的语句,必须手动检查状态(如GET DIAGNOSTICS或标志变量)并显式ROLLBACK
在 EXIT HANDLER 里只 SET 变量却不 ROLLBACK,事务会卡住;连接释放时可能被自动回滚,但调用方完全感知不到。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
ROLLBACK 必须显式写,RESIGNAL 强烈建议加上
ROLLBACK 不是可选操作,而是事务可靠性的底线:
- handler 里只写
ROLLBACK不够——调用方很可能收不到错误信息,变成“静默失败” - 加
RESIGNAL才能让原始错误透出到客户端(比如 Python 的pymysql.err.IntegrityError) - 若 handler 中做了自定义日志或补偿操作,
RESIGNAL必须放在最后,否则后续语句不执行
典型写法:
DECLARE EXIT HANDLER FOR SQLSTATE '23000' BEGIN
INSERT INTO error_log(msg, created_at) VALUES ('Duplicate key', NOW());
ROLLBACK;
RESIGNAL;
END;
最容易被忽略的底层限制:MyISAM 和 DDL 会破坏事务边界
哪怕 handler 写得再规范,以下两点不验证就形同虚设:
- MyISAM 表不支持事务,写了
START TRANSACTION和ROLLBACK也无效 -
ALTER TABLE、CREATE TABLE等 DDL 语句会隐式提交,导致前面的INSERT无法回滚
嵌套存储过程也是高发区:MySQL 不支持真正嵌套事务,子过程里的 COMMIT 会把父过程的整个事务提前提交掉——后续即使出错,ROLLBACK 也无事务可滚。










