You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让MariaDB在事务内语句失败时回滚整个事务?

如何让MariaDB在事务语句失败时回滚整个事务

问题说明

多数数据库管理系统(DBMS)中,事务内某条语句执行失败会触发整个事务回滚,但MariaDB/MySQL默认仅回滚失败的语句。例如执行以下SQL后,事务中成功插入的banana记录会保留:

DROP TABLE IF EXISTS test;
CREATE TABLE test (
    id INT PRIMARY KEY AUTO_INCREMENT,
    code INT CHECK(code>0),
    data VARCHAR(255)
) ENGINE=INNODB;

INSERT INTO test(code,data) VALUES(23,'apple');

START TRANSACTION;

INSERT INTO test(code,data) VALUES(45,'banana');
INSERT INTO test(code,data) VALUES(-3,'banjo');     -- 违反CHECK约束执行失败
COMMIT;

SELECT * FROM test;

解决方案

要让MariaDB在事务出错时回滚整个事务,可通过以下方式实现:

1. 临时开启会话级严格模式

在事务执行前运行以下命令,设置会话的sql_mode为传统模式:

SET SESSION sql_mode = 'STRICT_ALL_TABLES,TRADITIONAL';

TRADITIONAL模式会让MariaDB在遇到语句执行错误时立即终止事务,并回滚所有已完成的操作,符合标准事务的原子性要求。

2. 手动捕获错误并触发回滚

在SQL脚本或存储过程中,通过错误处理机制主动触发回滚。示例存储过程如下:

DELIMITER //
CREATE PROCEDURE insert_test_records()
BEGIN
    -- 捕获所有SQL异常,触发回滚
    DECLARE EXIT HANDLER FOR SQLEXCEPTION
    BEGIN
        ROLLBACK;
        SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '事务执行失败,已回滚所有操作';
    END;

    START TRANSACTION;
    INSERT INTO test(code,data) VALUES(45,'banana');
    INSERT INTO test(code,data) VALUES(-3,'banjo');
    COMMIT;
END //
DELIMITER ;

调用该存储过程时,只要任意一条语句执行失败,就会自动回滚整个事务。

3. 全局配置永久生效

若希望所有会话都遵循该规则,可修改MariaDB配置文件(如my.cnf/my.ini),在[mysqld]段落添加:

sql_mode = STRICT_ALL_TABLES,TRADITIONAL

保存配置后重启MariaDB服务,该设置将永久生效。

内容的提问来源于stack exchange,提问作者Manngo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 06:03:26