如何在内存中进行事务处理?
我对使用事务RDBMS非常熟悉,但是如果事务失败,我如何确保对内存中数据所做的更改被回滚? 如果我甚至不使用数据库怎么办?
这是一个人为的例子:
public void TransactionalMethod() { var items = GetListOfItems(); foreach (var item in items) { MethodThatMayThrowException(item); item.Processed = true; } }
在我的示例中,我可能希望以某种方式回滚对列表中项目所做的更改,但是如何实现此目的呢?
我知道“软件事务记忆”,但对它知之甚少,似乎相当实验性。 我也知道“可补偿交易”的概念,但这会产生编写执行/撤销代码的开销。
Subversion似乎通过让你运行“cleanup”命令来处理更新工作副本的错误。
有任何想法吗?
更新:
Reed Copsey提供了一个很好的答案 ,包括:
处理数据副本,在提交时更新原始数据。
这使我的问题更进一步 – 如果在提交期间发生错误怎么办? 我们经常将提交视为即时操作,但实际上它可能会对大量数据进行许多更改。 如果在应用提交时存在不可避免的事情,例如OutOfMemoryException
会发生什么?
另一方面,如果有人选择回滚选项,如果在回滚期间出现exception会发生什么? 我理解像Oracle RDBMS这样的东西有回滚段和UNDO日志和东西的概念,但假设没有序列化到磁盘(如果它没有序列化到磁盘,它没有发生,崩溃意味着你可以调查这些日志并从中恢复),这真的可能吗?
更新2:
Alex的回答提出了一个很好的建议:即更新一个不同的对象,然后,提交阶段只是将对当前对象的引用更改为新对象。 他进一步建议你改变的对象实际上是修改对象的列表。
我明白他在说什么(我想),我想让问题更复杂:
在这种情况下,你如何处理锁定? 想象一下,你有一个客户列表:
var customers = new Dictionary();
现在,您想要对其中一些客户进行更改,如何在不锁定和替换整个列表的情况下应用这些更改? 例如:
var customerTx = new Dictionary(); foreach (var customer in customers.Values) { var updatedCust = customer.Clone(); customerTx.Add(GetKey(updatedCust), updatedCust); if (CalculateRevenueMightThrowException(customer) >= 10000) { updatedCust.Preferred = true; } }
我该怎么做? 这(Alex的建议)意味着在替换列表引用时锁定所有客户:
lock (customers) { customers = customerTx; }
然而,如果我循环,修改原始列表中的引用,它不是primefaces的,并且与“如果它在中途崩溃的问题”相违背:
foreach (var kvp in customerTx) { customers[kvp.Key] = kvp.Value; }
几乎所有这样做的选择都需要以下三种基本方法之一:
- 在修改之前复制数据,如果中止则恢复为回滚状态。
- 处理数据副本,在提交时更新原始数据。
- 记录您的数据更改,以便在中止时撤消它们。
例如,您提到的软件事务内存遵循第三种方法。 关于这一点的好处是它可以乐观地处理数据,并且只是在成功提交时丢弃日志。
看一下Microsoft Research项目SXM 。
从Maurice Herlihy的页面 ,您可以下载文档和代码示例。
您询问:
“如果在提交期间发生错误怎么办?”
没关系。 您可以提交到内存中的某个/某些内容,同时检查操作是否成功。 如果是,则将目标对象(对象A)的引用更改为您提交的对象(对象B)。 然后你有failafe提交 – 只有在成功提交时才会更新引用。 参考变化是primefaces的。
public void TransactionalMethod() { var items = GetListOfItems(); try { foreach (var item in items) { MethodThatMayThrowException(item); item.Processed = true; } } catch(Exception ex) { foreach (var item in items) { if (item.Processed) { UndoProcessingForThisItem(item); } } } }
显然,“撤销……”的实施仍然是读者的练习。