在mysql开发中,事务回滚用于撤销未提交的数据变更,确保多条sql语句要么全部成功要么全部失败。它依赖存储引擎的事务能力,最常用的是innodb。合理使用rollback可以避免脏数据,是后端开发的基本功。

一、mysql事务回滚的基本使用
使用事务回滚通常包含三个步骤:开启事务、执行sql、提交或回滚。在命令行或程序代码中都遵循这一逻辑。
1. 使用sql语句控制
可以先执行start transaction,再执行若干更新语句,出错时用rollback撤销,确认无误后用commit提交。
start transaction; update account set balance = balance - 100 where user_id = 1; update account set balance = balance + 100 where user_id = 2; -- 如果中间发生错误,执行下面一句回滚 rollback; -- 如果都成功,执行下面一句提交 commit;
2. 在程序中使用
以java的jdbc为例,需要关闭自动提交,执行操作后根据异常决定回滚或提交。
Connection conn = dataSource.getConnection();
conn.setAutoCommit(false);
try {
// 执行更新
PreparedStatement ps = conn.prepareStatement("update account set balance=balance-? where user_id=?");
ps.setInt(1, 100);
ps.setInt(2, 1);
ps.executeUpdate();
// 模拟出错
int x = 1 / 0;
conn.commit();
} catch (Exception e) {
conn.rollback();
} finally {
conn.close();
}
二、常见问题与解决方法
1. 回滚没有生效
如果使用myisam等不支持事务的存储引擎,rollback不会起作用。解决方法是把表改为innodb。
alter table account engine = innodb;
2. 自动提交未关闭
mysql默认autocommit为1,每条语句自动提交,此时rollback无效。需要在事务开始前关闭。
set autocommit = 0; start transaction;
3. 捕获异常但未回滚
代码中捕获了异常却只打印日志,没有调用rollback,会造成部分数据已提交。务必在catch中回滚。
4. 事务中使用了ddl语句
在事务里执行create、alter、truncate等ddl语句会隐式提交,导致前面操作无法回滚。应避免在事务中混用ddl。
| 问题 | 原因 | 处理 |
|---|---|---|
| 回滚无效 | 非事务引擎 | 改为innodb |
| 自动提交 | autocommit开启 | 设成0再开事务 |
| 部分提交 | 混用ddl | 拆分事务 |
三、小结
掌握mysql事务回滚,关键在确认存储引擎支持事务、控制好autocommit、在异常路径正确rollback,并避开ddl隐式提交。这样写出的数据层逻辑才足够稳健。