介绍
在本实验中,你将学习如何使用 MySQL 事务来确保数据完整性。事务将一系列 SQL 操作组合成一个单一的、要么全部成功要么全部失败的工作单元。这对于金融转账等任务至关重要,因为所有步骤都必须成功完成。
你将练习使用 BEGIN 启动事务,使用 COMMIT 使更改永久生效,使用 ROLLBACK 撤销更改,以及使用 SAVEPOINT 执行部分回滚。在本实验结束时,你将理解如何安全可靠地管理数据库操作。
在本实验中,你将学习如何使用 MySQL 事务来确保数据完整性。事务将一系列 SQL 操作组合成一个单一的、要么全部成功要么全部失败的工作单元。这对于金融转账等任务至关重要,因为所有步骤都必须成功完成。
你将练习使用 BEGIN 启动事务,使用 COMMIT 使更改永久生效,使用 ROLLBACK 撤销更改,以及使用 SAVEPOINT 执行部分回滚。在本实验结束时,你将理解如何安全可靠地管理数据库操作。
在处理事务之前,你需要设置一个数据库和一张表。在此步骤中,你将创建一个名为 bank_db 的数据库和一个 accounts 表来模拟银行业务。
首先,从你的桌面打开终端。
以 root 用户连接到 MySQL 服务器。此实验环境不需要为 root 用户设置密码。
sudo mysql -u root
连接成功后,你将看到 MySQL 提示符 (mysql>),这表明你现在可以运行 SQL 命令了。
创建 bank_db 数据库,并在当前会话中切换到该数据库。IF NOT EXISTS 子句可以防止在数据库已存在时报错。
CREATE DATABASE IF NOT EXISTS bank_db;
USE bank_db;
接下来,创建 accounts 表。此表将存储账户信息,包括 ID、账号和余额。
CREATE TABLE accounts (
id INT AUTO_INCREMENT PRIMARY KEY,
account_number VARCHAR(20) UNIQUE NOT NULL,
balance DECIMAL(10, 2) NOT NULL
);
现在,向 accounts 表中插入两个示例账户。这些将作为我们的初始数据。
INSERT INTO accounts (account_number, balance) VALUES
('ACC001', 1000.00),
('ACC002', 500.00);
为了确认表和数据已正确创建,请运行以下查询:
SELECT * FROM accounts;
你应该会看到你刚刚插入的两个账户。输出将如下所示:
+----+----------------+---------+
| id | account_number | balance |
+----+----------------+---------+
| 1 | ACC001 | 1000.00 |
| 2 | ACC002 | 500.00 |
+----+----------------+---------+
2 rows in set (0.00 sec)
数据库和表准备就绪后,你就可以开始学习事务了。
BEGIN 和 COMMIT 创建成功事务事务是作为单个逻辑单元执行的一系列操作。要使更改永久生效,你必须 COMMIT 它们。在此步骤中,你将模拟一次从 ACC001 到 ACC002 的成功银行转账。
你应该仍然处于上一步的 MySQL shell 中。
首先,使用 BEGIN 命令启动一个新事务。所有后续命令都将成为此事务的一部分,直到你 COMMIT 或 ROLLBACK。
BEGIN;
现在,执行转账的两个操作:从 ACC001 扣除 $100,并向 ACC002 添加 $100。
UPDATE accounts SET balance = balance - 100.00 WHERE account_number = 'ACC001';
UPDATE accounts SET balance = balance + 100.00 WHERE account_number = 'ACC002';
此时,更改仅在你当前会话中可见。你可以检查账户的临时状态:
SELECT * FROM accounts;
输出将显示更新后的余额,但它们尚未永久保存。
+----+----------------+---------+
| id | account_number | balance |
+----+----------------+---------+
| 1 | ACC001 | 900.00 |
| 2 | ACC002 | 600.00 |
+----+----------------+---------+
2 rows in set (0.00 sec)
由于两个操作都成功了,你可以通过提交事务使更改永久生效。
COMMIT;
COMMIT 命令会保存事务期间所做的所有更改。转账现已完成,并且对所有其他数据库连接可见。你可以通过再次查询表来验证这一点。余额将保持在 $900 和 $600。
ROLLBACK 撤销事务有时,事务中的某个操作会失败,或者你可能决定取消它。ROLLBACK 命令会丢弃当前事务中进行的所有更改,将数据库恢复到事务开始之前的状态。
让我们开始一个新事务来添加一个新账户。
BEGIN;
现在,将新账户 ACC003 插入 accounts 表。
INSERT INTO accounts (account_number, balance) VALUES ('ACC003', 150.00);
检查表以查看事务中的新账户。
SELECT * FROM accounts;
你将看到列出了三个账户。
+----+----------------+---------+
| id | account_number | balance |
+----+----------------+---------+
| 1 | ACC001 | 900.00 |
| 2 | ACC002 | 600.00 |
| 3 | ACC003 | 150.00 |
+----+----------------+---------+
3 rows in set (0.00 sec)
现在,假设你意识到不应该添加这个账户。与其提交,不如使用 ROLLBACK 取消整个事务。
ROLLBACK;
此命令会撤销 INSERT 操作。要验证这一点,请再次查询 accounts 表。
SELECT * FROM accounts;
ACC003 账户已消失,表已恢复到你输入 BEGIN 之前的状态。
+----+----------------+---------+
| id | account_number | balance |
+----+----------------+---------+
| 1 | ACC001 | 900.00 |
| 2 | ACC002 | 600.00 |
+----+----------------+---------+
2 rows in set (0.00 sec)
ROLLBACK 是在发生错误时维护数据完整性的关键工具。
SAVEPOINT 进行部分回滚对于长时间运行的事务,你可能希望只撤销部分工作,而不是整个事务。SAVEPOINT 允许你在事务中设置一个标记,之后可以回滚到该标记。
让我们开始一个新事务。
BEGIN;
首先,更新 ACC001 的余额,增加 $50。
UPDATE accounts SET balance = balance + 50.00 WHERE account_number = 'ACC001';
现在,创建一个保存点(savepoint)。这充当了事务当前状态的书签。
SAVEPOINT after_update;
接下来,执行另一个操作:插入一个新账户 ACC004。
INSERT INTO accounts (account_number, balance) VALUES ('ACC004', 300.00);
假设插入 ACC004 是个错误,但对 ACC001 的更新是正确的。你可以回滚到保存点,只撤销 INSERT 语句。
ROLLBACK TO after_update;
此命令会将事务恢复到创建 after_update 保存点时的状态。ACC004 的插入被撤销,但对 ACC001 的更新仍然保留。
查询表以确认。ACC004 应该消失了,但 ACC001 的余额应该已更新。
SELECT * FROM accounts;
输出应显示 ACC001 的余额为 $950.00,并且没有 ACC004。
+----+----------------+---------+
| id | account_number | balance |
+----+----------------+---------+
| 1 | ACC001 | 950.00 |
| 2 | ACC002 | 600.00 |
+----+----------------+---------+
2 rows in set (0.00 sec)
由于你想保留对 ACC001 的更新,现在可以提交事务的剩余部分。
COMMIT;
你已成功使用保存点执行了部分回滚。现在可以退出 MySQL shell。
exit;
在本实验中,你学习了 MySQL 事务的基础知识,以维护数据完整性。你实践了完整的事务生命周期,从使用 BEGIN 开始事务,到使用 COMMIT 完成事务或使用 ROLLBACK 取消事务。
你成功模拟了银行转账,确保多个操作被视为一个单一的原子单元。你还学会了如何使用 SAVEPOINT 通过启用部分回滚来对复杂事务进行更精细地控制。这些技能对于开发健壮可靠的数据库应用程序至关重要,在这些应用程序中,数据一致性是至关重要的。