【问题标题】:LMDB: Rolling back transactions without rolling back everythingLMDB:回滚事务而不回滚所有内容
【发布时间】:2017-09-01 13:02:07
【问题描述】:

我有一个使用 LMDB 的应用程序。如果多个进程需要写入数据库,一次只允许运行一个,其余的则阻塞。因此,我想重写应用程序以使用客户端-服务器模型。

如果应用程序被编写为使用客户端-服务器模型,服务器可以管理写入并且其他进程不会阻塞。但是,如果一个客户端遇到错误必须回滚它的事务,它如何在不回滚其他客户端写的内容的情况下回滚它的数据呢?

我看过嵌套事务,但写事务可能只有一个嵌套事务。因此,虽然客户端可以将其数据写入嵌套事务并在发生错误时将其回滚,但一次只能运行一个客户端。因此,虽然这解决了回滚问题,但我们又回到了一个客户端一次只能写入的问题。

我还查看了 MDB_NOLOCK 选项,它会导致 LMDB 不会阻止您创建多个写入事务。当您尝试提交除第一个之外的任何事务时,它将返回错误。也许客户端可以将他们的写入汇集到他们自己的事务中,并且当他们准备好提交时,服务器会将条目转储到第一个写入事务中,但这很麻烦,我敢肯定这不是开发人员想要的用于。

我能想到的唯一其他解决方案是将客户端保留在单独的数据库中,这会取消切换到客户端-服务器模型的全部目的。

是否有任何其他方法可以允许不同的进程写入数据库,同时能够回滚一个客户端的数据而不回滚所有内容?

【问题讨论】:

    标签: database lmdb


    【解决方案1】:

    对于您提出的挑战,没有简单的解决方案。

    可以将写入事务嵌套任意深度,但正如您所说,这并不能帮助您获得更好的吞吐量,因为您仍然会被限制为该写入事务的一个线程。因此,对于大多数意图和目的而言,如果您按照设计使用的 LMDB 来使用,那么您将只有一个线程在数据库上执行写入操作。

    您问过如何在不回滚其他人的交易的情况下中止某人的交易。这在很大程度上不是问题,因为如上所述,您一次只有一个写入事务处于活动状态。如果您在请求结束时提交并在下一个请求开始时开始新事务,则您的写入事务将不会重叠。一旦您提交了第一个事务,您将无法中止它,但如果您的客户端通知服务器在提交之前中止请求,您的服务器可以中止它。当它中止时,数据库状态将恢复到该事务启动时的状态。它不会丢失任何其他事务,也不会丢失其他请求创建的更改。

    正如您所指出的,您可以将一些写入请求批处理到单个写入 txn。您可以在其他线程中处理其中一些写入请求,但所有 LMDB API 调用仍必须在原始线程中完成。而且,如果您尝试为每个请求指定一个线程以实现某种并行性,您仍然需要确保请求相互兼容并且不会相互干扰。如果其中一个请求遇到麻烦,您将不得不中止事务并可能重新启动事务。当您重新启动事务时,您可能只会包含没有遇到麻烦的请求。 -- 这一切皆有可能,但只有您对您的应用程序有足够的了解,才能知道这是否会大大提高性能并值得您付出努力。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-29
      • 1970-01-01
      • 2021-06-19
      • 2011-09-19
      • 1970-01-01
      • 2013-07-02
      相关资源
      最近更新 更多