学习笔记:数据库——事务
1.内容:
基于现有数据库设计检查点实验,观察比较提交前后执行结果并分析。
2.实现
源码
-- 开启事务
START TRANSACTION;-- 插入一条订单记录(客户ID为10002)
INSERT INTO orders (o_date, c_id) VALUES (NOW(), 10002);-- 获取生成的订单号
SET @order_id := LAST_INSERT_ID();-- 插入第1条订单项(A003)
INSERT INTO orderitems (o_num, o_item, f_id, quantity, item_price)
VALUES (@order_id, 1, 'A001', 2, 5.99);-- 设置保存点S1
SAVEPOINT S1;-- 插入第2条订单项(A002)
INSERT INTO orderitems (o_num, o_item, f_id, quantity, item_price)
VALUES (@order_id, 2, 'A002', 1, 3.50);-- 设置保存点S2
SAVEPOINT S2;-- 插入第3条订单项(A001)
INSERT INTO orderitems (o_num, o_item, f_id, quantity, item_price)
VALUES (@order_id, 3, 'A003', 5, 4.20);-- 设置保存点S3
SAVEPOINT S3;-- 回滚到保存点S2(撤销A001插入)
ROLLBACK TO S2;-- 提交事务,最终只保留 A003 和 A002 两条记录
COMMIT;-- 查询确认结果
SELECT * FROM orderitems WHERE o_num = @order_id;
运行测试结果截图:
事务rollback TO S2之前 缓冲区的orders表格:
事务rollback TO S2之后 缓冲区的orders表格:
解释原因:
具体执行顺序如下:
1.插入订单主表数据(orders),生成订单号
2.插入三条订单明细(orderitems):分别为 A001、A002 和 A003;
3.每插入一条订单项后设置一个保存点(S1、S2、S3);
4.执行 ROLLBACK TO S2,表示撤销从保存点 S2 之后的所有操作,也就是撤销了 A003 的插入;
5.执行 COMMIT 提交事务,此时数据库中只保留在 S2 之前成功执行的操作:A001 和 A002。
之所以插入的 A001 数据没有被提交,是因为它发生在保存点 S2 之后,回滚到 S2 时被撤销了。回滚不会影响 S2 之前已执行的 SQL 语句。
2.实验中产生的错误及原因分析
在使用 ROLLBACK TO 保存点 时,曾出现“保存点回滚后数据异常”的情况。
原因在于误将 SAVEPOINT 放在 INSERT 语句之前,导致即使回滚也不会撤销之后的插入操作。
调整语句顺序为“插入后设置保存点”后,回滚行为符合预期,成功撤销了指定操作。