在咱们的课程里,事务这个东西会讲三次。每次都会有新发现。现在先来搞懂事务的基础。等到课程后半段再聊聊事务隔离级别,最后还会说说嵌套事务的细节。
什么是事务
先来点简单的——定义。事务就是一组必须一起执行的操作。 就是这样。
所以有个很重要的结论:如果这组操作里有任何一个出错了,那就得把其他所有操作的结果都撤销,把系统恢复到最初的状态。
从 SQL 的角度看,事务就是一组操作(比如插入、更新或删除数据),它保证要么事务里的所有操作都成功,要么一个都不执行。这种机制让数据库操作变得可靠又一致,尤其是在处理支付或者更新关联数据这种关键场景下特别重要。
想象一下你在两个银行账户之间转钱。简单来说,就是两个连续的操作:
- 从一个账户扣钱。
- 把同样的钱加到另一个账户。
如果在最后一步出错(比如服务器挂了),很重要的一点是不能让任何一个用户吃亏。换句话说,要么两步都成功(事务提交),要么两步都撤销(事务回滚)。
事务和 ACID 原则
事务是基于 ACID 原则的,这个原则提醒我们有四个关键特性:
- Atomicity(原子性):要么全做,要么全不做。事务里的所有操作要么都执行,要么都撤销。
- Consistency(一致性):事务前后,数据都得是正确的状态。
- Isolation(隔离性):每个事务都像自己是系统里唯一的事务一样运行。
- Durability(持久性):事务提交后,数据就算服务器挂了也不会丢。
管理事务的基本命令
准备好实操了吗!下面是管理事务最重要的三条命令:
BEGIN
开始一个新事务。后面的所有操作都会在这个事务里执行。COMMIT
提交更改。执行完这条命令后,所有操作都变成永久的。ROLLBACK
撤销更改。如果哪里出错了,可以回滚事务,数据会恢复到原来的状态。
事务的基本语法
事务的简单结构:
BEGIN;
-- 这里写你的 SQL 操作
COMMIT;
ROLLBACK 的用法示例:
BEGIN;
-- 修改 students 表
UPDATE students
SET grade = grade + 10
WHERE id = 1;
-- 哦!发现这是个错误。
ROLLBACK;
实际场景下事务的用法示例
假设我们有这些表:
students:
| id | name | grade |
|---|---|---|
| 1 | Otto Lin | 85 |
| 2 | Anna Song | 90 |
courses:
| course_id | course_name |
|---|---|
| 1 | 数学 |
| 2 | 历史 |
比如我们想让某个学生同时选课并更新他的平均分:
BEGIN;
-- 步骤 1:往“选课记录”表插入一条记录
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- 步骤 2:更新学生的平均分
UPDATE students
SET grade = grade + 5
WHERE id = 1;
COMMIT;
如果服务器在第一步和第二步之间挂了会怎样?如果没用事务,数据就会不一致:选课记录加上了,但平均分没变。但用了事务,这两个操作要么都成功,要么都撤销。
事务里的错误处理
有时候事情会出错,这时候就得好好处理错误。在 PostgreSQL 里,如果出错,事务会自动回滚。
我们来故意出个错看看会发生啥。假设 course_enrollments 表里的 student_id 列有唯一性约束。我们试着插入重复的数据:
BEGIN;
INSERT INTO course_enrollments (student_id, course_id)
VALUES (1, 2);
-- 事务结束(还没提交)
COMMIT;
如果插入的学生已经选过这门课,就会报错,PostgreSQL 会自动回滚事务。
用 ROLLBACK 手动回滚
有时候错误是预料不到的,这时候你就可以手动回滚事务:
BEGIN;
-- 添加新学生
INSERT INTO students (name, grade)
VALUES ('Omori Sanny', 75);
-- 哎呀!发现学生是误加的。
ROLLBACK;
执行 ROLLBACK 后,表不会变——Omori Sanny 并没有出现在 students 里。
实用建议和常见错误
用事务的时候,记住几个重要的规则会让你轻松很多:
- 只要你的操作有两个以上步骤,尤其是要改多个表的数据时,一定要用事务。
- 别忘了提交更改(
COMMIT)。不然事务就一直没结束,数据也不会变。 - 复杂操作都用事务包起来,保证数据一致性。
- 只要发现有错,别犹豫,直接用
ROLLBACK。
现在你已经知道怎么用事务来控制操作了,是时候动手练练,继续学习事务,保证数据完整性啦!
GO TO FULL VERSION