菜鸟科技网

MySQL事务命令有哪些核心用法与注意事项?

什么是事务?

事务是一个工作单元,它是一系列操作的集合,这些操作要么全部成功执行,要么全部失败回滚,不会出现部分成功部分失败的情况,事务确保了数据的一致性完整性

MySQL事务命令有哪些核心用法与注意事项?-图1
(图片来源网络,侵删)

一个经典的例子就是银行转账:

  1. 从 A 账户扣款。
  2. 向 B 账户存款。

这两个操作必须作为一个整体,如果第一步成功但第二步失败(例如系统崩溃),A 的钱就凭空消失了,事务可以保证在这种异常情况下,A 的钱会自动退回。


事务的 ACID 特性

理解事务通常从它的四个核心特性开始:

  1. 原子性:事务是一个不可分割的工作单元,事务中的操作要么全部发生,要么全部不发生。
  2. 一致性:事务必须使数据库从一个一致性状态变换到另一个一致性状态,转账前后,A 和 B 的总金额是不变的。
  3. 隔离性:多个并发的事务之间是相互隔离的,一个事务的执行不能被其他事务干扰,即,一个事务内部的操作及所需的数据对并发的其他事务是隔离的。
  4. 持久性:一旦事务被提交,它对数据库中数据的改变就是永久性的,即使数据库发生故障(如断电、宕机),数据库也能恢复到事务成功结束时的状态。

MySQL 事务的核心命令

开始事务

命令: START TRANSACTION;BEGIN;

MySQL事务命令有哪些核心用法与注意事项?-图2
(图片来源网络,侵删)
  • 作用: 显式地开启一个事务,从这条语句执行开始,之后的 SQL 语句都将在这个事务中执行,直到遇到 COMMITROLLBACK
  • 注意: 如果不使用 START TRANSACTION,那么每条 SQL 语句都会在执行后被自动提交(即 autocommit=1 的状态)。
START TRANSACTION;
-- 或者
BEGIN;

提交事务

命令: COMMIT;

  • 作用: 提交当前事务,它将事务中所有对数据库的修改永久保存到数据库中,一旦提交,事务结束,autocommit 模式会重新生效。
  • 效果: 在 COMMIT 执行之前,其他会话是看不到这些修改的(隔离性保证)。COMMIT 之后,修改对所有会话可见。
-- 执行一系列操作...
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
-- 确认无误后,提交事务
COMMIT;

回滚事务

命令: ROLLBACK;

  • 作用: 回滚当前事务,它会撤销自 START TRANSACTIONBEGIN 之后所有未提交的 SQL 操作,将数据库恢复到事务开始之前的状态。
  • 使用场景: 当事务执行过程中发生错误,或者业务逻辑判断需要取消操作时,使用 ROLLBACK 来保证数据的一致性。
START TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- 在这里假设发生了错误,或者业务逻辑不满足
-- ...
-- 回滚所有操作
ROLLBACK;

设置保存点

命令: SAVEPOINT savepoint_name;

  • 作用: 在当前事务中设置一个保存点,保存点是一个标记,你可以将事务回滚到这个标记点,而不是回滚到事务的开始。
  • 优点: 相比于只能全部回滚的 ROLLBACK,保存点提供了更细粒度的回滚控制。
START TRANSACTION;
-- 操作1
DELETE FROM orders WHERE order_id = 101;
SAVEPOINT sp1; -- 设置保存点 sp1
-- 操作2
DELETE FROM customers WHERE customer_id = 501;
SAVEPOINT sp2; -- 设置保存点 sp2
-- 如果发现操作2有问题,但操作1是正确的
-- 可以只回滚到 sp2,撤销操作2
ROLLBACK TO sp2;
-- 如果确认所有操作都没问题,再提交整个事务
COMMIT;

释放保存点

命令: RELEASE SAVEPOINT savepoint_name;

MySQL事务命令有哪些核心用法与注意事项?-图3
(图片来源网络,侵删)
  • 作用: 删除(释放)一个之前设置的保存点,当保存点不再需要时,可以释放它。
  • 注意: 当事务提交或回滚(非回滚到保存点)时,所有在该事务中创建的保存点都会被自动释放。
-- ... (在事务中)
RELEASE SAVEPOINT sp1;

一个完整的事务示例

下面是一个完整的银行转账事务示例,演示了 START TRANSACTION, COMMITROLLBACK 的使用。

场景: 用户 A (ID=1) 给用户 B (ID=2) 转账 100 元。

-- 1. 查看初始余额
SELECT user_id, balance FROM accounts;
-- 假设 A 的余额是 1000, B 的余额是 500
-- 2. 开始事务
START TRANSACTION;
-- 3. 执行核心操作
-- 从 A 的账户扣款
UPDATE accounts SET balance = balance - 100 WHERE user_id = 1;
-- 检查是否扣款成功 (可选,但推荐)
-- A 的余额不足,后续操作应该回滚
-- SELECT balance FROM accounts WHERE user_id = 1 FOR UPDATE; -- 使用 FOR UPDATE 锁定行
-- 向 B 的账户存款
UPDATE accounts SET balance = balance + 100 WHERE user_id = 2;
-- 4. 模拟一个错误,以便演示 ROLLBACK
-- 假设在这里我们检查到 A 的余额不足,或者业务逻辑不满足
-- 我们主动触发一个错误来回滚
-- SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '余额不足,转账失败!';
-- 或者,我们手动决定回滚
-- ROLLBACK; -- 取消注释这行来演示回滚
-- 5. 如果一切正常,提交事务
-- COMMIT; -- 取消注释这行来演示提交
-- 6. 再次查看余额,验证结果
-- 如果执行了 COMMIT,A 的余额变为 900,B 的变为 600。
-- 如果执行了 ROLLBACK,余额将恢复到初始状态 (1000 和 500)。
SELECT user_id, balance FROM accounts;

与事务相关的系统变量

autocommit

  • 作用: 控制是否自动提交。autocommit 是一个会话级别的变量。
  • 默认值: ON (1),这意味着每条单独的 DML 语句(INSERT, UPDATE, DELETE)执行完毕后,都会立即被提交。
  • 如何查看:
    SELECT @@autocommit;
  • 如何设置:
    -- 关闭自动提交
    SET autocommit = 0;
    -- 开启自动提交
    SET autocommit = 1;
  • 重要提示: 当你使用 START TRANSACTIONBEGIN 显式开启一个事务时,当前会话的 autocommit 会被临时设置为 OFF,直到事务被 COMMITROLLBACKautocommit 会恢复到之前的值。

transaction_isolation

  • 作用: 设置事务的隔离级别,决定了事务之间的可见性。
  • 如何查看:
    SELECT @@transaction_isolation;
  • 如何设置 (会话级别):
    SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
  • 常见隔离级别:
    • READ UNCOMMITTED: 最低级别,可以读到未提交的数据。
    • READ COMMITTED (RC): 默认级别(MySQL 8.0.3+),只能读取到已提交的数据。
    • REPEATABLE READ (RR): MySQL 的默认级别(8.0.3 之前),保证在同一个事务中多次读取同样数据的结果是一致的。
    • SERIALIZABLE: 最高级别,强制事务串行执行,性能最低,但隔离性最强。

最佳实践

  1. 保持事务尽可能短: 事务开始后,应尽快执行完毕并提交或回滚,长时间运行的事务会锁定数据库资源,影响其他会话的性能。
  2. 明确使用 START TRANSACTION: 不要依赖 autocommit,显式地开启和结束事务可以让代码逻辑更清晰。
  3. 在业务逻辑层处理错误: 不要仅仅依靠数据库的错误来回滚,在应用程序代码中,通过 try...catch 等机制捕获异常,并在异常发生时调用 ROLLBACK
  4. 合理使用保存点: 对于复杂事务,使用保存点可以避免因一个小错误而回滚整个事务,提高灵活性。
  5. 注意锁的使用: 在事务中,特别是查询和更新数据时,要小心锁,使用 SELECT ... FOR UPDATE 可以锁定查询的行,防止其他事务在当前事务结束前修改它们,这有助于保证数据一致性,但也可能导致死锁。
分享:
扫描分享到社交APP
上一篇
下一篇