使用 Berkeley DB 事务处理的问题
Posted
技术标签:
【中文标题】使用 Berkeley DB 事务处理的问题【英文标题】:Problems Using the Berkeley DB Transactional Processing 【发布时间】:2016-09-20 22:10:14 【问题描述】:我正在编写一组程序,这些程序必须在一个公共数据库上运行,可能是并发的。为了简单起见(对于用户),我不想要求设置数据库服务器。因此,我选择了 Berkeley DB,在那里可以启动一个程序,如果它不存在,则让它创建它。
为了让程序在数据库上同时工作,必须使用 5.x 版本中的事务功能(这里我使用 python3-bsddb3 6.1.0-1+b2 和 libdb5.3 5.3.28- 12):文档明确说可以做到。然而我很快就遇到了麻烦,即使有一些基本任务:
程序 1 初始化表中的记录 程序 2 必须扫描程序 1 之前添加的记录,并使用其他数据更新它们。为了加快速度,有一个用于所述附加数据的索引。当程序 1 创建记录时,附加数据不存在,因此指向该记录的指针被添加到空键下的索引中。然后程序 2 可以快速查找尚未更新的记录。
即使没有同时运行,记录更新程序也会在几次更新后崩溃。首先它抱怨互斥区空间不足。我不得不用一个不起眼的 DB_CONFIG 文件解决这个问题,然后运行 db_recover。
接下来,在几次更新后,它再次抱怨“无法分配内存——BDB3017 无法从缓冲区缓存中分配空间”。 db_recover 并重新启动程序就成功了,只是它在几条记录后再次崩溃并出现相同的错误。
我什至没有提到并发使用:当其中一个程序在另一个程序运行时启动时,它们几乎立即因死锁而崩溃,对损坏的段感到恐慌并要求运行恢复。我做了很多更改,所以我遇到了各种各样的错误,这些错误在搜索时通常会产生不相关的匹配项。我什至重写了 db 调用以使用 lmdb,它实际上工作得很好并且非常快,这往往表明我的程序逻辑没有错误。不幸的是,lmdb 生成的数据文件似乎非常稀疏,并且很快增长到无法接受的大小。
从我所说的来看,似乎某些资源正在某个地方泄漏。我很犹豫是否直接在 C 中重写所有这些,以检查问题是否来自 Python 绑定。
我可以并且我会用代码更新问题,但目前 ti 已经足够长了。我正在寻找在 BDB 中使用过事务性东西的人,用于类似用途,这可能会指出一些问题。
谢谢
【问题讨论】:
【参考方案1】:RPM(参见http://rpm5.org)在事务模式下使用 Berkeley DB。有相当多的陷阱,具体取决于您的尝试。
您已经找到 DB_CONFIG:您必须配置互斥锁和锁的大小,默认值总是太小。
在开发过程中需要运行 db_recover 也很痛苦。最好的解决方法(恕我直言)是在打开时通过检查 DB_RUNRECOVERY 的返回码来自动恢复,然后使用 DB_RECOVER 重新打开 dbenv。
死锁通常是设计/编码错误:运行 db_stat -CA 以查看死锁(或持有哪些锁)并调整您的程序。 “与 lmdv 一起工作”不足以声明工作代码;-)
使用 -fsanitize:address 的 valgrind 和/或 BDB 编译可以看到泄漏。请注意,除非您使用覆盖和/或编译 BDB 来初始化,否则 valgrind 将报告错误的未初始化。
【讨论】:
以上是关于使用 Berkeley DB 事务处理的问题的主要内容,如果未能解决你的问题,请参考以下文章