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