事务 #
一、事务概述 #
事务是一组操作的逻辑单元,要么全部成功,要么全部失败。
1.1 ACID特性 #
| 特性 | 说明 |
|---|---|
| Atomicity | 原子性:事务不可分割 |
| Consistency | 一致性:事务前后数据一致 |
| Isolation | 隔离性:事务之间互不影响 |
| Durability | 持久性:事务提交后永久保存 |
1.2 事务类型 #
| 类型 | 说明 |
|---|---|
| 单文档事务 | 单个文档操作自动事务 |
| 多文档事务 | 显式事务处理多个文档 |
| JavaScript事务 | 使用JavaScript API |
二、单文档事务 #
2.1 自动事务 #
单文档操作自动具有ACID特性:
aql
INSERT { name: "张三" } INTO users
aql
UPDATE "user_001" WITH { age: 29 } IN users
2.2 单文档原子性 #
aql
INSERT {
_key: "user_001",
name: "张三",
balance: 1000
} INTO users
三、JavaScript事务 #
3.1 基本事务 #
javascript
db._executeTransaction({
collections: {
write: ["users", "accounts"]
},
action: function() {
var db = require("@arangodb").db;
db.users.insert({ name: "张三" });
db.accounts.insert({ userId: "张三", balance: 0 });
}
});
3.2 事务参数 #
javascript
db._executeTransaction({
collections: {
read: ["users"],
write: ["orders", "products"]
},
action: function(params) {
var db = require("@arangodb").db;
var user = db.users.document(params.userId);
var product = db.products.document(params.productId);
if (product.stock < params.quantity) {
throw new Error("库存不足");
}
db.orders.insert({
userId: params.userId,
productId: params.productId,
quantity: params.quantity
});
db.products.update(params.productId, {
stock: product.stock - params.quantity
});
return { success: true };
},
params: {
userId: "user_001",
productId: "product_001",
quantity: 2
}
});
3.3 事务选项 #
javascript
db._executeTransaction({
collections: { write: ["users"] },
action: function() {
// 事务操作
},
waitForSync: true,
lockTimeout: 30
});
四、AQL事务 #
4.1 单语句事务 #
aql
LET user = DOCUMENT("users/user_001")
LET product = DOCUMENT("products/product_001")
LET order = {
userId: user._key,
productId: product._key,
quantity: 2,
amount: product.price * 2
}
INSERT order INTO orders
UPDATE product._key WITH {
stock: product.stock - 2
} IN products
RETURN NEW
4.2 使用LET组织事务 #
aql
LET fromUser = DOCUMENT("users/user_001")
LET toUser = DOCUMENT("users/user_002")
LET amount = 100
FILTER fromUser.balance >= amount
UPDATE fromUser._key WITH {
balance: fromUser.balance - amount
} IN users
UPDATE toUser._key WITH {
balance: toUser.balance + amount
} IN users
INSERT {
from: fromUser._key,
to: toUser._key,
amount: amount,
createdAt: DATE_NOW()
} INTO transactions
RETURN { success: true }
五、事务隔离级别 #
5.1 隔离级别 #
ArangoDB支持快照隔离:
text
隔离级别:
├── 读已提交
├── 可重复读
└── 快照隔离
5.2 并发控制 #
javascript
db._executeTransaction({
collections: { write: ["accounts"] },
action: function() {
var db = require("@arangodb").db;
var account = db.accounts.document("account_001");
// 检查余额
if (account.balance < 100) {
throw new Error("余额不足");
}
// 扣款
db.accounts.update("account_001", {
balance: account.balance - 100
});
}
});
六、转账事务示例 #
6.1 完整转账事务 #
javascript
function transfer(fromId, toId, amount) {
return db._executeTransaction({
collections: { write: ["accounts", "transactions"] },
action: function() {
var db = require("@arangodb").db;
var from = db.accounts.document(fromId);
var to = db.accounts.document(toId);
if (from.balance < amount) {
throw new Error("余额不足");
}
if (from.status !== "active" || to.status !== "active") {
throw new Error("账户状态异常");
}
db.accounts.update(fromId, {
balance: from.balance - amount
});
db.accounts.update(toId, {
balance: to.balance + amount
});
db.transactions.insert({
from: fromId,
to: toId,
amount: amount,
type: "transfer",
createdAt: new Date().toISOString()
});
return {
success: true,
fromBalance: from.balance - amount,
toBalance: to.balance + amount
};
}
});
}
6.2 调用转账 #
javascript
try {
var result = transfer("account_001", "account_002", 100);
print(result);
} catch (e) {
print("转账失败: " + e.message);
}
七、库存扣减事务 #
7.1 库存事务 #
javascript
function createOrder(userId, items) {
return db._executeTransaction({
collections: {
read: ["users"],
write: ["orders", "products", "orderItems"]
},
action: function() {
var db = require("@arangodb").db;
var user = db.users.document(userId);
if (user.status !== "active") {
throw new Error("用户状态异常");
}
var totalAmount = 0;
var orderItems = [];
for (var i = 0; i < items.length; i++) {
var item = items[i];
var product = db.products.document(item.productId);
if (product.stock < item.quantity) {
throw new Error("商品 " + product.name + " 库存不足");
}
var itemAmount = product.price * item.quantity;
totalAmount += itemAmount;
orderItems.push({
productId: item.productId,
productName: product.name,
quantity: item.quantity,
price: product.price,
amount: itemAmount
});
db.products.update(item.productId, {
stock: product.stock - item.quantity
});
}
var order = db.orders.insert({
userId: userId,
items: orderItems,
totalAmount: totalAmount,
status: "pending",
createdAt: new Date().toISOString()
});
for (var j = 0; j < orderItems.length; j++) {
db.orderItems.insert({
orderId: order._key,
productId: orderItems[j].productId,
quantity: orderItems[j].quantity,
price: orderItems[j].price
});
}
return {
orderId: order._key,
totalAmount: totalAmount
};
}
});
}
八、事务错误处理 #
8.1 回滚 #
事务中抛出异常会自动回滚:
javascript
db._executeTransaction({
collections: { write: ["users"] },
action: function() {
var db = require("@arangodb").db;
db.users.insert({ name: "张三" });
if (someCondition) {
throw new Error("条件不满足,回滚事务");
}
db.users.insert({ name: "李四" });
}
});
8.2 错误捕获 #
javascript
try {
db._executeTransaction({
collections: { write: ["accounts"] },
action: function() {
var db = require("@arangodb").db;
var account = db.accounts.document("account_001");
if (account.balance < 100) {
throw new Error("余额不足");
}
db.accounts.update("account_001", {
balance: account.balance - 100
});
}
});
} catch (e) {
print("事务失败: " + e.message);
}
九、事务性能 #
9.1 事务最佳实践 #
text
建议:
├── 事务尽量简短
├── 减少锁定的集合数量
├── 避免长时间运行的事务
├── 合理设置超时时间
└── 避免热点数据竞争
9.2 锁超时 #
javascript
db._executeTransaction({
collections: { write: ["users"] },
action: function() {
// 事务操作
},
lockTimeout: 60
});
9.3 同步写入 #
javascript
db._executeTransaction({
collections: { write: ["users"] },
action: function() {
// 事务操作
},
waitForSync: true
});
十、流式事务 #
10.1 开始事务 #
javascript
var trx = db._createTransaction({
collections: { write: ["users"] }
});
10.2 执行操作 #
javascript
trx.query(`
INSERT { name: "张三" } INTO users
`);
10.3 提交事务 #
javascript
trx.commit();
10.4 中止事务 #
javascript
trx.abort();
十一、总结 #
事务要点:
- ACID特性:原子性、一致性、隔离性、持久性
- 单文档事务:自动事务
- JavaScript事务:db._executeTransaction()
- 隔离级别:快照隔离
- 错误处理:异常自动回滚
下一步,让我们学习Foxx微服务!
最后更新:2026-03-27