【发布时间】:2012-09-11 16:40:45
【问题描述】:
我意识到,就其本质而言,MongoDB 不会也可能永远不会支持此类事务。但是,我发现我确实需要以某种有限的方式使用它们,所以我提出了以下解决方案,我想知道:这是最好的方法吗,可以吗?需要改进吗?(在我在我的应用中实现它之前!)
显然,事务是通过应用程序控制的(在我的例子中,是一个 Python 网络应用程序)。对于此事务中的每个文档(在任何集合中),都添加了以下字段:
'lock_status': bool (true = locked, false = unlocked),
'data_old': dict (of any old values - current values really - that are being changed),
'data_new': dict (of values replacing the old (current) values - should be an identical list to data_old),
'change_complete': bool (true = the update to this specific document has occurred and was successful),
'transaction_id': ObjectId of the parent transaction
此外,还有一个transaction 集合,用于存储详细说明每个正在进行的交易的文档。它们看起来像:
{
'_id': ObjectId,
'date_added': datetime,
'status': bool (true = all changes successful, false = in progress),
'collections': array of collection names involved in the transaction
}
这是流程的逻辑。希望它以这样一种方式工作,即如果它被中断或以其他方式失败,它可以正确回滚。
1:设置transaction文档
2:对于受此事务影响的每个文档:
- 将
lock_status设置为true(以“锁定”文档不被修改) - 将
data_old和data_new设置为它们的旧值和新值 - 将
change_complete设置为false - 将
transaction_id设置为我们刚刚创建的transaction文档的ObjectId
3:执行更新。对于每个受影响的文档:
- 用
data_new值替换该文档中所有受影响的字段 - 将
change_complete设置为true
4:将transaction文档的status设置为true(因为所有数据都修改成功了)
5:对于受交易影响的每个文档,做一些清理:
- 删除
data_old和data_new,因为它们不再需要 - 将
lock_status设置为false(解锁文档)
6:删除在步骤 1 中设置的transaction 文档(或按照建议,将其标记为完成)
我认为从逻辑上讲,如果它在任何时候失败,所有数据都可以回滚或继续事务(取决于你想要做什么)。显然所有回滚/恢复/等。由应用程序而不是数据库执行,方法是使用 transaction 文档和具有该 transaction_id 的其他集合中的文档。
这个逻辑中是否有我遗漏或忽略的明显错误?有没有更有效的方法(例如,减少对数据库的写入/读取)?
【问题讨论】:
标签: mongodb transactions