跳转到主要内容
模块 8 · 第 4 课(共 4)课程中的32/57~10 min
模块课程(4/4)

交易:全有或全无

事务是数据库视为的一组操作 单个单位:要么他们全部成功,要么他们都没有留下 踪迹。当序列出现时,这就是您如何保护自己免受不一致的影响 UPDATE/INSERT/DELETE 必须保持一致。

语法

SQL
BEGIN;             -- apri la transazione

UPDATE …;
INSERT …;
DELETE …;
SELECT …;          -- puoi anche solo leggere

COMMIT;            -- conferma tutte le modifiche
-- oppure
ROLLBACK;          -- annulla tutte le modifiche, come se nulla fosse

BEGIN 和 COMMIT 之间的所有内容都是原子的:没有其他连接 看到中间状态。如果程序崩溃或执行 ROLLBACK,数据库与 BEGIN 之前完全相同。

经典场景:转账

典型的例子是产品之间的库存转移(或货币) 帐户之间的转账):两个 UPDATE 必须一起, 从来没有一个是,另一个不是。

SQL
BEGIN;
UPDATE products SET stock = stock - 1 WHERE id = 1;
UPDATE products SET stock = stock + 1 WHERE id = 2;
COMMIT;

如果第二个 UPDATE 失败(例如 CHECK 约束错误), ROLLBACK 将产品 1 的库存恢复到其原始值。

ROLLBACK:DBA 的调试器

SQL
BEGIN;
UPDATE customers SET city = 'X' WHERE id = 1;
SELECT first_name, city FROM customers WHERE id = 1;   -- "vedo come è cambiato"
ROLLBACK;

在真实数据上尝试 UPDATE 的一个非常有用的模式:您 运行它,在同一事务中使用 SELECT 检查结果,并且 如果它不能说服你,你 ROLLBACK — 数据库完全一样 那是以前。

SAVEPOINT:部分回滚

在交易内部,您可以创建中间点:

SQL
BEGIN;
UPDATE customers SET city = 'A' WHERE id = 1;
SAVEPOINT step1;
UPDATE customers SET city = 'B' WHERE id = 2;
-- mi sono accorto che il secondo UPDATE è sbagliato:
ROLLBACK TO SAVEPOINT step1;
COMMIT;     -- solo il primo UPDATE viene confermato

30秒内酸

事务保证 ACID 属性:

  • Atomicity — 全有或全无;
  • C一致性——在交易开始和结束时约束保持满足;
  • Isolation — 并发事务看不到中间状态(在不同的“级别”);
  • D耐用性 - 即使发生崩溃,成功的 COMMIT 也不会丢失。

轮到你了

锻炼#sql.m8.l4.e1
尝试:0加载中...

在单个事务中:将产品 1 的库存减 1,将产品 2 的库存加 1。用 BEGIN 打开,用 COMMIT 关闭。

正在加载编辑器...
显示提示

相应 SET 条款中的参考库存 - 1 和库存 + 1。

3 次尝试后可用的解决方案

复习练习

锻炼#sql.m8.l4.e2
尝试:0加载中...

打开一个事务,尝试将 id=1 的客户所在城市更新为 'Sperimentale',然后使用 ROLLBACK 取消操作。最后,客户 1 的城市必须是原始城市(“米兰”)。

正在加载编辑器...
显示提示

ROLLBACK 取消从 BEGIN 开始所做的所有更改。

3 次尝试后可用的解决方案