事务 #

一、事务概述 #

事务是一组操作的逻辑单元,要么全部成功,要么全部失败。

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();

十一、总结 #

事务要点:

  1. ACID特性:原子性、一致性、隔离性、持久性
  2. 单文档事务:自动事务
  3. JavaScript事务:db._executeTransaction()
  4. 隔离级别:快照隔离
  5. 错误处理:异常自动回滚

下一步,让我们学习Foxx微服务!

最后更新:2026-03-27