事务处理 #
一、事务概述 #
1.1 ACID特性 #
text
FaunaDB事务特性:
├── 原子性(Atomicity)
│ └── 事务中的所有操作要么全部成功,要么全部失败
├── 一致性(Consistency)
│ └── 事务前后数据保持一致状态
├── 隔离性(Isolation)
│ └── 并发事务互不干扰
└── 持久性(Durability)
└── 已提交的事务永久保存
1.2 事务特点 #
text
FaunaDB事务特点:
├── 每个查询都是一个事务
├── 自动提交
├── 串行化隔离级别
├── 无需显式开始/提交
└── 支持Abort回滚
二、基本事务 #
2.1 单语句事务 #
javascript
// 单语句自动是事务
Create(Collection("users"), {
data: { name: "Tom", email: "tom@example.com" }
})
2.2 多语句事务 #
javascript
// Do组合多个操作
Do(
Create(Collection("users"), {
data: { name: "Tom" }
}),
Create(Collection("profiles"), {
data: { userId: "tom" }
}),
Create(Collection("audit_logs"), {
data: { action: "user_created", timestamp: Now() }
})
)
2.3 事务返回值 #
javascript
// Do返回最后一个表达式的值
Let(
{
result: Do(
Create(Collection("users"), { data: { name: "Tom" } }),
Create(Collection("profiles"), { data: { userId: "tom" } }),
{ success: true, message: "User created" }
)
},
Var("result")
)
三、Abort回滚 #
3.1 Abort语法 #
javascript
// Abort中止事务
If(
condition,
doSomething,
Abort("Transaction failed: reason")
)
3.2 条件回滚 #
javascript
// 条件检查后回滚
Let(
{
userRef: Ref(Collection("users"), "user_001"),
balance: Select(["data", "balance"], Get(Var("userRef"))),
amount: 100
},
If(
LT(Var("balance"), Var("amount")),
Abort("Insufficient balance"),
Update(Var("userRef"), {
data: {
balance: Subtract(Var("balance"), Var("amount"))
}
})
)
)
3.3 多条件验证 #
javascript
// 多条件验证
Let(
{
orderRef: Ref(Collection("orders"), "order_001"),
order: Get(Var("orderRef")),
status: Select(["data", "status"], Var("order")),
total: Select(["data", "total"], Var("order")),
payment: Select(["data", "payment"], Var("order"))
},
If(
Not(Equals(Var("status"), "pending")),
Abort("Order is not in pending status"),
If(
LT(Var("payment"), Var("total")),
Abort("Payment amount is insufficient"),
If(
Not(Exists(Select(["data", "user"], Var("order")))),
Abort("User not found"),
Update(Var("orderRef"), {
data: {
status: "paid",
paidAt: Now()
}
})
)
)
)
)
四、转账事务 #
4.1 简单转账 #
javascript
// 转账事务
Let(
{
fromRef: Ref(Collection("accounts"), "account_001"),
toRef: Ref(Collection("accounts"), "account_002"),
amount: 100,
fromAccount: Get(Var("fromRef")),
toAccount: Get(Var("toRef")),
fromBalance: Select(["data", "balance"], Var("fromAccount")),
toBalance: Select(["data", "balance"], Var("toAccount"))
},
If(
LT(Var("fromBalance"), Var("amount")),
Abort("Insufficient balance"),
Do(
Update(Var("fromRef"), {
data: { balance: Subtract(Var("fromBalance"), Var("amount")) }
}),
Update(Var("toRef"), {
data: { balance: Add(Var("toBalance"), Var("amount")) }
}),
Create(Collection("transactions"), {
data: {
from: Var("fromRef"),
to: Var("toRef"),
amount: Var("amount"),
timestamp: Now()
}
})
)
)
)
4.2 带锁定的转账 #
javascript
// 使用时间戳乐观锁
Let(
{
fromRef: Ref(Collection("accounts"), "account_001"),
toRef: Ref(Collection("accounts"), "account_002"),
amount: 100,
expectedFromTs: Var("clientFromTs"),
expectedToTs: Var("clientToTs")
},
Let(
{
fromAccount: Get(Var("fromRef")),
toAccount: Get(Var("toRef")),
currentFromTs: Select(["ts"], Var("fromAccount")),
currentToTs: Select(["ts"], Var("toAccount"))
},
If(
And(
Equals(Var("currentFromTs"), Var("expectedFromTs")),
Equals(Var("currentToTs"), Var("expectedToTs"))
),
If(
LT(Select(["data", "balance"], Var("fromAccount")), Var("amount")),
Abort("Insufficient balance"),
Do(
Update(Var("fromRef"), {
data: {
balance: Subtract(
Select(["data", "balance"], Var("fromAccount")),
Var("amount")
)
}
}),
Update(Var("toRef"), {
data: {
balance: Add(
Select(["data", "balance"], Var("toAccount")),
Var("amount")
)
}
}),
Create(Collection("transactions"), {
data: {
from: Var("fromRef"),
to: Var("toRef"),
amount: Var("amount"),
timestamp: Now()
}
})
)
),
Abort("Account was modified by another transaction")
)
)
)
五、库存事务 #
5.1 库存扣减 #
javascript
// 库存扣减事务
Let(
{
productRef: Ref(Collection("products"), "prod_001"),
quantity: 5,
product: Get(Var("productRef")),
currentStock: Select(["data", "stock"], Var("product"))
},
If(
LT(Var("currentStock"), Var("quantity")),
Abort("Insufficient stock"),
Update(Var("productRef"), {
data: {
stock: Subtract(Var("currentStock"), Var("quantity")),
updatedAt: Now()
}
})
)
)
5.2 订单创建事务 #
javascript
// 创建订单并扣减库存
Let(
{
userId: "user_001",
items: [
{ productId: "prod_001", quantity: 2 },
{ productId: "prod_002", quantity: 1 }
]
},
Do(
// 验证并扣减库存
Foreach(
Var("items"),
Lambda("item",
Let(
{
productRef: Ref(Collection("products"), Select("productId", Var("item"))),
quantity: Select("quantity", Var("item")),
product: Get(Var("productRef")),
stock: Select(["data", "stock"], Var("product"))
},
If(
LT(Var("stock"), Var("quantity")),
Abort(Concat([
"Insufficient stock for product: ",
Select("productId", Var("item"))
])),
Update(Var("productRef"), {
data: {
stock: Subtract(Var("stock"), Var("quantity"))
}
})
)
)
)
),
// 创建订单
Create(Collection("orders"), {
data: {
user: Ref(Collection("users"), Var("userId")),
items: Var("items"),
status: "pending",
createdAt: Now()
}
})
)
)
六、并发控制 #
6.1 乐观并发控制 #
javascript
// 使用时间戳的乐观锁
Let(
{
ref: Ref(Collection("documents"), "doc_001"),
expectedTs: Var("clientTs"),
doc: Get(Var("ref")),
currentTs: Select(["ts"], Var("doc"))
},
If(
Equals(Var("currentTs"), Var("expectedTs")),
Update(Var("ref"), {
data: { content: Var("newContent") }
}),
Abort("Document was modified by another transaction")
)
)
6.2 版本号控制 #
javascript
// 使用版本号
Let(
{
ref: Ref(Collection("documents"), "doc_001"),
expectedVersion: Var("clientVersion"),
doc: Get(Var("ref")),
currentVersion: Select(["data", "version"], Var("doc"), 0)
},
If(
Equals(Var("currentVersion"), Var("expectedVersion")),
Update(Var("ref"), {
data: {
content: Var("newContent"),
version: Add(Var("currentVersion"), 1)
}
}),
Abort("Document version mismatch")
)
)
6.3 重试机制 #
javascript
// 重试函数
CreateFunction({
name: "retry_update",
body: Query(
Lambda(["ref", "updateFn", "maxRetries"],
Let(
{
attempt: Query(
Lambda(["retries"],
Let(
{
doc: Get(Var("ref")),
result: Var("updateFn")(Var("doc"))
},
If(
Equals(Var("result"), "retry"),
If(
LT(Var("retries"), Var("maxRetries")),
Call(Function("retry_update"), [
Var("ref"),
Var("updateFn"),
Var("maxRetries")
]),
Abort("Max retries exceeded")
),
Var("result")
)
)
)
)
},
Call(Var("attempt"), [0])
)
)
)
})
七、事务最佳实践 #
7.1 保持事务简短 #
javascript
// 好的做法:简洁的事务
Do(
Update(userRef, { data: { balance: newBalance } }),
Create(transactions, { data: transactionData })
)
// 避免:复杂的长事务
Do(
// 大量操作...
// 可能导致超时
)
7.2 提前验证 #
javascript
// 提前验证条件
Let(
{
user: Get(userRef),
product: Get(productRef),
userValid: Equals(Select(["data", "status"], Var("user")), "active"),
productValid: GT(Select(["data", "stock"], Var("product")), 0)
},
If(
Not(Var("userValid")),
Abort("User is not active"),
If(
Not(Var("productValid")),
Abort("Product out of stock"),
// 执行事务
Do(
// ...
)
)
)
)
7.3 记录审计日志 #
javascript
// 带审计日志的事务
Let(
{
operation: "transfer",
userId: "user_001"
},
Do(
// 业务操作
Update(accountRef, { data: { balance: newBalance } }),
// 审计日志
Create(Collection("audit_logs"), {
data: {
operation: Var("operation"),
userId: Var("userId"),
timestamp: Now(),
details: { amount: 100 }
}
})
)
)
八、实际应用示例 #
8.1 银行转账 #
javascript
// 完整的银行转账事务
Let(
{
fromAccountId: "account_001",
toAccountId: "account_002",
amount: 100,
description: "Transfer"
},
Let(
{
fromRef: Ref(Collection("accounts"), Var("fromAccountId")),
toRef: Ref(Collection("accounts"), Var("toAccountId")),
fromAccount: Get(Var("fromRef")),
toAccount: Get(Var("toRef")),
fromBalance: Select(["data", "balance"], Var("fromAccount")),
toBalance: Select(["data", "balance"], Var("toAccount"))
},
If(
LT(Var("fromBalance"), Var("amount")),
Abort("Insufficient balance"),
If(
Equals(Var("fromRef"), Var("toRef")),
Abort("Cannot transfer to same account"),
Do(
// 更新账户余额
Update(Var("fromRef"), {
data: {
balance: Subtract(Var("fromBalance"), Var("amount")),
updatedAt: Now()
}
}),
Update(Var("toRef"), {
data: {
balance: Add(Var("toBalance"), Var("amount")),
updatedAt: Now()
}
}),
// 创建交易记录
Create(Collection("transactions"), {
data: {
type: "transfer",
from: Var("fromRef"),
to: Var("toRef"),
amount: Var("amount"),
description: Var("description"),
status: "completed",
timestamp: Now()
}
})
)
)
)
)
)
8.2 订单支付 #
javascript
// 订单支付事务
Let(
{
orderId: "order_001",
paymentMethod: "credit_card"
},
Let(
{
orderRef: Ref(Collection("orders"), Var("orderId")),
order: Get(Var("orderRef")),
status: Select(["data", "status"], Var("order")),
total: Select(["data", "total"], Var("order")),
userId: Select(["data", "userId"], Var("order"))
},
If(
Not(Equals(Var("status"), "pending")),
Abort("Order is not in pending status"),
Let(
{
userRef: Ref(Collection("users"), Var("userId")),
user: Get(Var("userRef")),
balance: Select(["data", "balance"], Var("user"))
},
If(
LT(Var("balance"), Var("total")),
Abort("Insufficient user balance"),
Do(
// 扣除用户余额
Update(Var("userRef"), {
data: {
balance: Subtract(Var("balance"), Var("total")),
updatedAt: Now()
}
}),
// 更新订单状态
Update(Var("orderRef"), {
data: {
status: "paid",
paymentMethod: Var("paymentMethod"),
paidAt: Now(),
updatedAt: Now()
}
}),
// 创建支付记录
Create(Collection("payments"), {
data: {
order: Var("orderRef"),
user: Var("userRef"),
amount: Var("total"),
method: Var("paymentMethod"),
status: "completed",
timestamp: Now()
}
})
)
)
)
)
)
)
九、总结 #
事务处理要点:
| 特性 | 说明 |
|---|---|
| ACID | 原子性、一致性、隔离性、持久性 |
| Do | 组合多个操作 |
| Abort | 中止事务 |
| 乐观锁 | 使用时间戳或版本号 |
| 串行化 | 最高隔离级别 |
下一步,让我们学习用户定义函数!
最后更新:2026-03-27