在开发后台系统时,我们经常需要同时执行多条MySQL语句来完成一个业务动作。如果这些语句之间具有强关联,并且任意一条失败都会让数据处于不完整状态,那么就应该使用事务来保证安全。MySQL事务依靠ACID特性,让一组操作要么全部成功,要么全部回滚。
什么是MySQL事务
事务是一组SQL操作的逻辑单元。它具备四个特性:原子性保证操作不可分割,一致性确保数据约束不被破坏,隔离性处理并发可见性,持久性意味着提交后数据永久保存。在InnoDB引擎中,事务是默认支持的能力。
应该使用事务的典型场景
1. 资金转账
转账必须从一个账户扣款并向另一个账户加款。若只完成一步,就会出现钱丢失或凭空增加的问题。
2. 订单与库存
用户下单时,要插入订单记录并减少商品库存。任一步失败都应撤销,否则会超卖或产生孤儿订单。
3. 批量数据维护
当多个表需要同步更新,例如修改用户资料同时更新积分与日志,也应放在一个事务里。
基础代码示例
下面以PHP使用PDO为例,展示转账场景的事务写法:
<?php
try {
$pdo = new PDO('mysql:host=127.0.0.1;dbname=test', 'user', 'pass');
$pdo->beginTransaction();
// 从A账户扣款
$pdo->exec("UPDATE account SET balance = balance - 100 WHERE id = 1");
// 向B账户加款
$pdo->exec("UPDATE account SET balance = balance + 100 WHERE id = 2");
$pdo->commit();
echo '转账成功';
} catch (Exception $e) {
$pdo->rollBack();
echo '转账失败,已回滚';
}
?>
不使用事务的风险
如果上述操作不用事务,当第二条SQL因网络或约束错误中断,A账户钱已扣但B未加,数据便不一致。后期对账和修复成本很高。
| 场景 | 是否建议事务 | 原因 |
|---|---|---|
| 单条查询 | 否 | 只读操作无需一致性保障 |
| 单条插入 | 视情况 | 若与其他数据无关可不用 |
| 多表联动写 | 是 | 必须保证整体成功或失败 |
小结
判断要不要使用MySQL事务,核心看操作是否跨多条语句且要求数据一致。涉及钱、订单、库存以及多表同步时,请务必使用BEGIN、COMMIT与ROLLBACK保护好你的数据。