事务处理
本文档详细介绍 cDataBase 类的事务处理功能,包括事务的开始、提交、回滚等。
? 目录
事务概述
什么是事务
事务是一组数据库操作,要么全部成功,要么全部失败。事务具有以下特性(ACID):
- 原子性 (Atomicity) - 事务中的所有操作要么全部执行,要么全部不执行
- 一致性 (Consistency) - 事务执行前后数据库保持一致状态
- 隔离性 (Isolation) - 并发事务之间相互隔离
- 持久性 (Durability) - 事务提交后,数据永久保存
事务状态
开始事务
↓
执行操作 1
↓
执行操作 2
↓
执行操作 3
↓
提交事务 ──→ 成功:所有操作生效
│
└──→ 失败:自动回滚,所有操作撤销事务方法
TransBegin 方法
TransBegin 方法开始一个新事务。
语法
vb
Function TransBegin() As Boolean返回值
True- 事务开始成功False- 事务开始失败(可通过LastErr查看错误信息)
示例
vb
' 开始事务
If db.TransBegin Then
Debug.Print "事务已开始"
Else
Debug.Print "事务开始失败: " & db.LastErr
End IfTransCommit 方法
TransCommit 方法提交事务。
语法
vb
Function TransCommit() As Boolean功能
- 提交所有事务中的操作
- 如果提交失败,自动回滚
- 清除事务标记
返回值
True- 提交成功False- 提交失败(已自动回滚)
示例
vb
' 提交事务
If db.TransCommit Then
Debug.Print "事务提交成功"
Else
Debug.Print "事务提交失败,已自动回滚: " & db.LastErr
End IfTransRollback 方法
TransRollback 方法回滚事务。
语法
vb
Function TransRollback() As Boolean功能
- 撤销所有事务中的操作
- 清除事务标记
返回值
True- 回滚成功False- 回滚失败(可通过LastErr查看错误信息)
示例
vb
' 回滚事务
If db.TransRollback Then
Debug.Print "事务已回滚"
Else
Debug.Print "回滚失败: " & db.LastErr
End If基本使用
示例 1:简单事务
vb
' 开始事务
If db.TransBegin Then
' 执行操作 1
If db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec Then
' 执行操作 2
If db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题')").Exec Then
' 提交事务
If db.TransCommit Then
Debug.Print "事务提交成功"
Else
Debug.Print "提交失败,已自动回滚"
End If
Else
' 操作 2 失败,回滚
db.TransRollback
End If
Else
' 操作 1 失败,回滚
db.TransRollback
End If
End If示例 2:使用错误处理
vb
On Error GoTo ErrHandler
' 开始事务
If Not db.TransBegin Then
Debug.Print "事务开始失败: " & db.LastErr
Exit Sub
End If
' 执行多个操作
db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec
db.Sql("INSERT INTO users (name) VALUES ('李四')").Exec
db.Sql("UPDATE users SET status = 'active' WHERE name = '张三'").Exec
' 提交事务
If db.TransCommit Then
Debug.Print "所有操作成功"
Else
Debug.Print "提交失败: " & db.LastErr
End If
Exit Sub
ErrHandler:
' 发生错误,回滚事务
db.TransRollback
Debug.Print "发生错误,事务已回滚: " & Err.Description示例 3:转账操作
vb
' 转账操作:从账户 A 转 100 元到账户 B
Function TransferMoney(lFromAccount As Long, lToAccount As Long, dAmount As Double) As Boolean
On Error GoTo ErrHandler
' 开始事务
If Not db.TransBegin Then
TransferMoney = False
Exit Function
End If
' 从账户 A 扣除金额
Dim sSql As String
sSql = "UPDATE accounts SET balance = balance - " & dAmount & _
" WHERE id = " & lFromAccount & " AND balance >= " & dAmount
If Not db.Sql(sSql).Exec Then
db.TransRollback
TransferMoney = False
Exit Function
End If
' 检查是否有记录被更新
Dim lAffected As Long
If db.Sql("SELECT @@ROWCOUNT").Query Then
If db.Rs.EOF Or db.Rs(0) = 0 Then
db.TransRollback
TransferMoney = False
Exit Function
End If
End If
' 向账户 B 增加金额
sSql = "UPDATE accounts SET balance = balance + " & dAmount & _
" WHERE id = " & lToAccount
If Not db.Sql(sSql).Exec Then
db.TransRollback
TransferMoney = False
Exit Function
End If
' 记录转账日志
sSql = "INSERT INTO transfers (from_account, to_account, amount) VALUES (" & _
lFromAccount & ", " & lToAccount & ", " & dAmount & ")"
If Not db.Sql(sSql).Exec Then
db.TransRollback
TransferMoney = False
Exit Function
End If
' 提交事务
If db.TransCommit Then
TransferMoney = True
Else
TransferMoney = False
End If
Exit Function
ErrHandler:
db.TransRollback
TransferMoney = False
End Function错误处理
自动回滚机制
类库提供了自动回滚机制:
- 提交失败自动回滚 -
TransCommit失败时自动调用TransRollback - 断开连接自动回滚 -
Disconnect时自动回滚未完成的事务
vb
' 提交失败时自动回滚
If db.TransBegin Then
db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec
' 如果提交失败,会自动回滚
If Not db.TransCommit Then
Debug.Print "提交失败,已自动回滚: " & db.LastErr
End If
End If错误处理示例
vb
Function ExecuteTransaction() As Boolean
On Error GoTo ErrHandler
' 开始事务
If Not db.TransBegin Then
Debug.Print "事务开始失败: " & db.LastErr
ExecuteTransaction = False
Exit Function
End If
' 执行操作
If Not db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec Then
db.TransRollback
Debug.Print "操作失败: " & db.LastErr
ExecuteTransaction = False
Exit Function
End If
' 提交事务
If db.TransCommit Then
ExecuteTransaction = True
Else
Debug.Print "提交失败: " & db.LastErr
ExecuteTransaction = False
End If
Exit Function
ErrHandler:
' 发生异常,回滚事务
db.TransRollback
Debug.Print "异常发生,已回滚: " & Err.Description
ExecuteTransaction = False
End Function嵌套事务
注意事项
ADO 支持嵌套事务,但需要注意:
- 嵌套级别 - ADO 支持多级嵌套事务
- 提交顺序 - 必须按相反顺序提交(内层先提交)
- 回滚影响 - 回滚会影响所有嵌套级别
嵌套事务示例
vb
' 外层事务
If db.TransBegin Then
db.Sql("INSERT INTO users (name) VALUES ('用户1')").Exec
' 内层事务(嵌套)
If db.TransBegin Then
db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题1')").Exec
' 提交内层事务
If db.TransCommit Then
Debug.Print "内层事务提交成功"
End If
End If
' 提交外层事务
If db.TransCommit Then
Debug.Print "外层事务提交成功"
End If
End If最佳实践
1. 始终使用事务处理多个相关操作
vb
' ? 推荐:使用事务保证一致性
db.TransBegin
db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec
db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题')").Exec
db.TransCommit
' ? 不推荐:不使用事务
db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec
db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题')").Exec
' 如果第二个操作失败,第一个操作已经提交,数据不一致2. 检查每个操作的返回值
vb
' ? 推荐:检查每个操作
db.TransBegin
If Not db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec Then
db.TransRollback
Exit Sub
End If
If Not db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题')").Exec Then
db.TransRollback
Exit Sub
End If
db.TransCommit3. 使用错误处理
vb
' ? 推荐:使用错误处理
On Error GoTo ErrHandler
db.TransBegin
db.Sql("INSERT INTO users (name) VALUES ('张三')").Exec
db.Sql("INSERT INTO posts (user_id, title) VALUES (1, '标题')").Exec
db.TransCommit
Exit Sub
ErrHandler:
db.TransRollback
Debug.Print "错误: " & Err.Description4. 及时提交或回滚
vb
' ? 推荐:操作完成后立即提交或回滚
db.TransBegin
' ... 执行操作 ...
db.TransCommit ' 或 db.TransRollback
' ? 不推荐:长时间保持事务打开
db.TransBegin
' ... 执行操作 ...
' 等待用户输入(事务保持打开状态)
' ...
db.TransCommit5. 使用批量操作的事务
vb
' ? 推荐:批量操作使用事务
db.TransBegin
Dim i As Long
For i = 1 To 1000
If Not db.Sql("INSERT INTO users (name) VALUES ('用户" & i & "')").Exec Then
db.TransRollback
Exit For
End If
Next
If i > 1000 Then
db.TransCommit
End If常见问题
Q1: 事务提交后数据没有保存?
原因: 可能是数据库不支持事务,或者连接字符串配置问题。
解决:
- 检查数据库类型是否支持事务
- 验证连接字符串配置
Q2: 如何检查事务状态?
vb
' 注意:类库内部使用 IsTrans 标记,但不对外暴露
' 可以通过尝试提交来检查
If db.TransCommit Then
Debug.Print "有事务且提交成功"
Else
Debug.Print "没有事务或提交失败"
End IfQ3: 事务会影响性能吗?
回答: 是的,事务会锁定资源,影响并发性能。
建议:
- 尽量缩短事务时间
- 只包含必要的操作
- 避免在事务中进行长时间操作
最后更新: 2026-01-21