事务
在深入命令之前,必须理解事务 的概念。

事务是一个原子性 的操作序列,它要么全部成功,要么全部失败,它保证了数据库操作的一致性 和可靠性,一个典型的场景就是银行转账:
- 从账户 A 扣款。
- 向账户 B 存款。
这两个操作必须打包在一个事务中,如果第一步成功但第二步失败(比如系统崩溃),那么数据库会回滚,确保账户 A 的钱不会被无故扣除。
事务的四个核心特性(ACID):
- Atomicity (原子性): 事务内的所有操作,要么全部完成,要么全部不完成。
- Consistency (一致性): 事务必须使数据库从一个有效的状态转换到另一个有效的状态。
- Isolation (隔离性): 并发执行的事务是相互隔离的,一个事务的执行不应影响其他事务。
- Durability (持久性): 事务一旦提交,它对数据库的改变就是永久性的。
提交事务的关键命令
在 MySQL 中,默认情况下,每一条 INSERT, UPDATE, DELETE 语句都是一个独立的事务,并且会自动提交,但在需要执行多个相关操作的场景下,我们必须手动控制事务。

以下是手动控制事务的完整流程和命令:
START TRANSACTION 或 BEGIN
这个命令用于开启一个新的事务,它会暂时关闭 MySQL 的自动提交模式。
-- 开启一个事务 START TRANSACTION; -- 或者使用 BEGIN -- BEGIN;
执行 SQL 语句
在事务开启后,你可以执行一个或多个 INSERT, UPDATE, DELETE 语句,这些语句并不会立即永久地修改数据库,而是被“临时”保存在事务中。
-- 假设我们有一个 accounts 表 START TRANSACTION; -- 从账户 1 扣款 100 UPDATE accounts SET balance = balance - 100 WHERE id = 1; -- 向账户 2 存款 100 UPDATE accounts SET balance = balance + 100 WHERE id = 2; -- 如果查询数据库,会发现数据已经改变了,但这是暂时的。 -- 其他会话(连接)是看不到这些变化的。
COMMIT
这个命令用于提交事务,它会将事务中所有的操作永久地写入数据库,并结束当前事务,提交后,数据变更对所有会话都可见。
-- 提交事务,所有更改成为永久性 COMMIT;
执行 COMMIT 后会发生什么?
- 事务中的所有更改被写入数据库文件。
- 数据库的自动提交模式会重新启用(如果你之前关闭了它)。
- 事务结束。
ROLLBACK
这个命令用于回滚事务,它会撤销事务中所有尚未提交的 SQL 操作,将数据库恢复到事务开始之前的状态,这在发生错误或需要取消操作时非常有用。
-- 开启事务 START TRANSACTION; -- 执行一些操作 UPDATE products SET stock = stock - 1 WHERE id = 101; -- 突然发现产品 101 不存在,或者库存不够,需要取消操作 -- 回滚事务,所有更改被撤销 ROLLBACK; -- 执行 ROLLBACK 后,products 表的 stock 会回到执行 UPDATE 之前的状态。
完整示例:转账操作
下面是一个完整的、包含错误处理的转账事务示例。
-- 假设我们有如下表结构
CREATE TABLE accounts (
id INT PRIMARY KEY,
name VARCHAR(50),
balance DECIMAL(10, 2)
);
INSERT INTO accounts (id, name, balance) VALUES
(1, 'Alice', 1000.00),
(2, 'Bob', 500.00);
-- 场景1:成功转账
-- 1. 开启事务
START TRANSACTION;
-- 2. 执行操作
-- Alice 转给 Bob 200 元
UPDATE accounts SET balance = balance - 200 WHERE id = 1;
UPDATE accounts SET balance = balance + 200 WHERE id = 2;
-- 3. 提交事务
COMMIT;
-- 检查结果
SELECT * FROM accounts;
-- 结果: Alice 800, Bob 700,转账成功。
-- 场景2:转账失败并回滚
-- 1. 开启事务
START TRANSACTION;
-- 2. 执行操作
-- Alice 尝试转给 Bob 500 元(但她的余额只有 800)
UPDATE accounts SET balance = balance - 500 WHERE id = 1; -- Alice 变成 300
-- 模拟一个错误,Bob 的账户被冻结,无法接收转账
-- 我们故意执行一个会失败的更新
UPDATE accounts SET balance = balance + 500 WHERE id = 999; -- id=999 的账户不存在,此语句报错
-- 3. 由于上面的语句出错,我们需要回滚
-- 在实际应用中,你可能会用程序逻辑(如 try-catch)来捕获错误并执行 ROLLBACK
ROLLBACK;
-- 4. 检查结果
SELECT * FROM accounts;
-- 结果: Alice 800, Bob 700,数据被恢复到转账之前的状态,保证了数据一致性。
自动提交模式
这是理解事务提交的一个关键点。
-
默认状态: MySQL 的客户端(命令行、连接库等)通常默认是自动提交模式 (
autocommit=1)。- 含义: 每一条单独的 SQL 语句(如
INSERT)在执行完毕后都会被自动COMMIT。 - 如何查看:
-- 在 MySQL 命令行中输入 SELECT @@autocommit; -- 返回 1 表示开启,0 表示关闭。
- 如何关闭:
-- 关闭自动提交,这样你就可以手动控制事务了 SET autocommit = 0;
关闭后,你必须手动使用
COMMIT或ROLLBACK来结束事务,否则事务会一直保持,直到你执行了其中一个命令或断开连接(断开连接时会自动ROLLBACK)。
- 含义: 每一条单独的 SQL 语句(如
-
最佳实践: 在需要进行复杂业务逻辑操作时,强烈建议先关闭自动提交,然后使用
START TRANSACTION,COMMIT,ROLLBACK来手动管理事务。
| 命令 | 作用 | 时机 |
|---|---|---|
START TRANSACTION; 或 BEGIN; |
开启一个新的事务,并关闭自动提交。 | 当你需要执行一组相关的、需要原子性保证的操作时。 |
COMMIT; |
提交当前事务,使其中的所有更改永久生效。 | 当事务中的所有操作都成功完成,确认要保存结果时。 |
ROLLBACK; |
回滚当前事务,撤销所有未提交的更改。 | 当事务中的某个操作失败,或者你决定取消整个事务时。 |
SET autocommit = 0; |
关闭自动提交模式。 | 在执行复杂事务前,通常先执行此命令。 |
SET autocommit = 1; |
开启自动提交模式。 | 当你完成手动事务管理,希望后续的每条语句都自动提交时。 |
掌握这些命令和事务的概念,对于保证数据库数据的完整性和一致性至关重要。
