数据库事务管理与并发控制详解
立即解锁
发布时间: 2025-08-23 00:32:28 阅读量: 6 订阅数: 17 


数据库系统:设计、实现与管理的核心概念
# 数据库事务管理与并发控制详解
## 1. 并发事务问题
### 1.1 丢失更新(Lost Updates)
丢失更新问题在多个事务并发操作同一数据时出现。例如,有两个事务 T1 和 T2 同时操作产品库存数量(PROD_QOH),初始值为 35。
| 时间 | 事务 | 步骤 | 存储值 |
| ---- | ---- | ---- | ---- |
| 1 | T1 | 读取 PROD_QOH | 35 |
| 2 | T2 | 读取 PROD_QOH | 35 |
| 3 | T1 | PROD_QOH = 35 + 100 | - |
| 4 | T2 | PROD_QOH = 35 - 30 | - |
| 5 | T1 | 写入 PROD_QOH(丢失更新) | 135 |
| 6 | T2 | 写入 PROD_QOH | 5 |
在这个过程中,T1 的更新结果被 T2 覆盖,导致 T1 的更新丢失。
### 1.2 未提交数据(Uncommitted Data)
当两个事务 T1 和 T2 并发执行,且 T2 访问了 T1 未提交的数据,之后 T1 回滚,就会出现未提交数据问题,违反了事务的隔离性。
假设 T1 是采购 100 个单位的操作,T2 是销售 30 个单位的操作。
| 事务 | 计算 |
| ---- | ---- |
| T1: 采购 100 个单位 | PROD_QOH = PROD_QOH + 100(回滚) |
| T2: 销售 30 个单位 | PROD_QOH = PROD_QOH - 30 |
正常情况下,串行执行这两个事务能得到正确结果:
| 时间 | 事务 | 步骤 | 存储值 |
| ---- | ---- | ---- | ---- |
| 1 | T1 | 读取 PROD_QOH | 35 |
| 2 | T1 | PROD_QOH = 35 + 100 | - |
| 3 | T1 | 写入 PROD_QOH | 135 |
| 4 | T1 | *****回滚***** | 35 |
| 5 | T2 | 读取 PROD_QOH | 35 |
| 6 | T2 | PROD_QOH = 35 - 30 | - |
| 7 | T2 | 写入 PROD_QOH | 5 |
但如果在 T2 开始执行后 T1 才回滚,就会出现问题:
| 时间 | 事务 | 步骤 | 存储值 |
| ---- | ---- | ---- | ---- |
| 1 | T1 | 读取 PROD_QOH | 35 |
| 2 | T1 | PROD_QOH = 35 + 100 | - |
| 3 | T1 | 写入 PROD_QOH | 135 |
| 4 | T2 | 读取 PROD_QOH(读取未提交数据) | 135 |
| 5 | T2 | PROD_QOH = 135 - 30 | - |
| 6 | T1 | *****回滚***** | 35 |
| 7 | T2 | 写入 PROD_QOH | 105 |
### 1.3 不一致检索(Inconsistent Retrievals)
不一致检索是指一个事务在另一个事务处理数据前后访问数据,从而得到不一致的结果。例如,T1 计算产品表中产品的总库存数量,同时 T2 更新了部分产品的库存数量。
事务 T1:
```sql
SELECT SUM(PROD_QOH) FROM PRODUCT;
```
事务 T2:
```sql
UPDATE PRODUCT SET PROD_QOH = PROD_QOH + 10 WHERE PROD_CODE = '1546-QQ2';
UPDATE PRODUCT SET PROD_QOH = PROD_QOH - 10 WHERE PROD_CODE = '1558-QW1';
COMMIT;
```
在执行过程中,T1 可能会读取到部分更新前的数据和部分更新后的数据,导致结果不一致。具体数据如下:
| 产品代码 | 更新前 PROD_QOH | 更新后 PROD_QOH |
| ---- | ---- | ---- |
| 11QER/31 | 8 | 8 |
| 13 - Q2/P2 | 32 | 32 |
| 1546 - QQ2 | 15 | (15 + 10) 25 |
| 1558 - QW1 | 23 | (23 - 10) 13 |
| 2232 - QTY | 8 | 8 |
| 2232 - QWE | 6 | 6 |
| 总计 | 92 | 92 |
T1 执行过程中的计算结果:
| 时间 | 事务 | 操作 | 值 | 总计 |
| ---- | ---- | ---- | ---- | ---- |
| 1 | T1 | 读取 PROD_CODE = '11QER/31' 的 PROD_QOH | 8 | 8 |
| 2 | T1 | 读取 PROD_CODE = '13 - Q2/P2' 的 PROD_QOH | 32 | 40 |
| 3 | T2 | 读取 PROD_CODE = '1546 - QQ2' 的 PROD_QOH | 15 | - |
| 4 | T2 | PROD_QOH = 15 + 10 | - | - |
| 5 | T2 | 写入 PROD_CODE = '1546 - QQ2' 的 PROD_QOH | 25 | - |
| 6 | T1 | 读取 PROD_CODE = '1546 - QQ2' 的 PROD_QOH | 25 | (更新后) 65 |
| 7 | T1 | 读取 PROD_CODE = '1558 - QW1' 的 PROD_QOH | 23 | (更新前) 88 |
| 8 | T2 | 读取 PROD_CODE = '1558 - QW1' 的 PROD_QOH | 23 | - |
| 9 | T2 | PRO
0
0
复制全文
相关推荐










