我有一个使用LMDB的应用程序。如果需要向数据库写入多个进程,则一次只能运行一个进程,而其余进程阻止。因此,我想重写应用程序以使用客户端 - 服务器模型。
如果编写应用程序以使用客户端 - 服务器模型,则服务器可以管理写入,而其他进程不会阻止。但是,如果客户端遇到错误并且必须回滚其事务,那么如何在不回滚其他客户端编写的内容的情况下回滚其数据?
我查看了嵌套事务,但写事务可能只有一个嵌套事务。因此,虽然客户端可以将其数据写入嵌套事务并在发生错误时将其回滚,但一次只能运行一个客户端。因此,虽然这解决了回滚问题,但我们又回到了一次只能写一个客户端的问题。
我还查看了MDB_NOLOCK选项,这会导致LMDB无法阻止您创建多个写入事务。当您尝试提交除第一个事务之外的任何事务时,它将返回错误。也许客户端可以将他们的写入汇集到他们自己的事务中,当他们准备提交时,服务器会将条目转储到第一个写入事务中,但这很麻烦,我确定这不是什么开发人员打算将其用于。
我能想到的唯一其他解决方案是将客户端保存在一个单独的数据库中,从而解除了切换到客户端 - 服务器模型的整个目的。
是否有其他方法允许不同的进程写入数据库,同时能够回滚一个客户端的数据而不回滚所有内容?
答案 0 :(得分:0)
你所面临的挑战没有简单的解决方案。
可以任意嵌套写入事务,但正如您所说,这无法帮助您实现更好的吞吐量,因为您仍将仅限于该写入事务的一个线程。因此,对于大多数意图和目的,如果您使用LMDB,因为它只是设计用于数据库。
你问过如何在不回滚别人的txn的情况下中止某人的交易。这在很大程度上不是问题,因为如上所述,您将只有一个写入事务处于活动状态。如果在请求结束时提交并在下一个请求开始时启动新事务,则写入事务将不会重叠。提交第一个事务后,您将无法中止它,但如果您的客户端通知服务器在提交请求之前中止该请求,则您的服务器可以中止该事务。当它中止时,数据库状态将采用该事务启动时所处的状态。它不会丢失任何其他事务,也不会丢失其他请求所创建的更改。
正如您所指出的,您可以将一些写入请求批处理到单个写入txn中。您可以在其他线程中处理其中一些写入请求,但所有 LMDB API调用仍必须在原始线程中完成。如果您尝试将一个线程专用于每个请求以实现某些并行性,您仍然需要确保请求是相互兼容的,并且不会相互干扰。如果其中一个请求遇到麻烦,您将不得不中止事务并可能重新启动事务。当您重新启动事务时,您可能只会包含未运行的请求。 - 这一切都是可能的,但只有您对应用程序有足够的了解才能知道这是否会提高性能并值得您付出努力。