检测读写之间文档的并发数据修改

时间:2015-05-12 08:32:23

标签: mongodb database-design concurrency nosql

我对从数据库中提取文档,根据某些外部条件运行某些计算,更新文档的某个字段然后保存文档的方案感兴趣,所有这些都在系统中可能有并发线程访问数据库。

为了便于理解,这是一个非常简单的例子。假设我有以下文件:

{
   ...
   items_average: 1234,
   last_10_items: [10,2187,2133, ...]
   ...
}

假设有一个新项目(X),需要做五件事:

  1. 从DB
  2. 中读取文档
  3. 删除last_10_items
  4. 中的第一个(最旧的)项目
  5. 将X添加到数组的末尾
  6. 重新计算平均值*并将其保存在items_average中。
  7. 将文档写入数据库
  8. *注意:选择平均计算是一个非常简单的例子,但问题应该考虑基于文档中存在的数据和新数据的更复杂的操作(即不能用{{解决的问题) 1}}运营商)

    这在单线程系统中很容易实现,但在并发系统中,如果2个线程想要遵循上述步骤,则可能会出现不一致,因为两者都会更新$inc和{{ 1}}值,不考虑和/或覆盖并发更改。

    所以,我的问题是如何处理这样的场景?有没有办法检查或反应在步骤1和5之间更改基础文档的事实?是否存在来自redis的WATCH或来自关系数据库的“并发修改错误”?

    由于

1 个答案:

答案 0 :(得分:0)

在数据库系统中,它使用类似于事务内存的内存检查和回滚方案。

简而言之,它只是监视您指定的共享内存部分,并执行比较和交换或加载和链接或测试和设置之类的操作。 因此,如果在事务期间更改了任何内存内容,它将中止并再次尝试,直到该共享内存没有冲突操作。

例如,GCC实现以下内容:

https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Atomic-Builtins.html

type __sync_lock_test_and_set (type *ptr, type value, ...)
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...)

有关事务内存的更多信息, http://en.wikipedia.org/wiki/Software_transactional_memory