【发布时间】:2011-07-04 06:11:39
【问题描述】:
我有一个 C++ 应用程序,它的内存数据集由一组对象组成,每个对象都附加了一个键/值集。对象和键由 int id 引用,值始终是单个类的实例。 Key id 在对象中是唯一的,对象 id 在 Universe 中是唯一的。
这几乎是map<pair<int, int>, value>,除了我需要能够枚举附加到特定对象的键的额外要求。这一切都需要是事务性的,所以如果出现问题,我可以回滚更改。
这一切都让我觉得这是一个完全标准的问题,我应该能够获得现成的代码,但我一直找不到任何东西。任何人都可以:
(a) 告诉我这个问题实际上叫什么,这样我就知道要查找什么了;
(b) 建议我应该查看的任何代码。
请注意,我希望这只是一个内存数据存储,因此像 Berkeley DB 这样的 NoSQL 方法不适合 --- 我不想继续读取和写入值对象(它是中等复杂的)。
到目前为止,我找到了不执行事务的简单方法(例如 boost_multi_index,甚至只是嵌套的 STL 映射),或者使用持久存储的复杂方法,但两者之间没有。我可以在基本存储之上实现自己的事务层,但老实说,我宁愿不这样做。
我错过了什么?
编辑:好吧,似乎没有人能够推荐一个;所以我写了我自己的。这是令人惊讶的繁琐但实际上并不是很多代码。现在它只是一个使用嵌套映射进行存储的模板类,但为了简单起见,我正在考虑改为使用 boost::multi_index_container。它没有完善,可能充满了错误,但如果有人认为他们可以使用它,请告诉我。
更多编辑:作为参考,我正在寻找的 Googleable 名称是一个实体/属性/值数据库 (EAV)。
【问题讨论】:
-
用 :memory: pseudo-DB 查看 SQLite
-
这仍然需要我在访问它们时序列化/反序列化我的值。我想使用本地数据存储,以便我的值只是指向 C++ 对象的指针,从而避免 I/O 开销。
-
我不太明白。在数据库中,您使用事务以避免导致部分成功的操作或其他客户端由于此类操作而看到不一致的状态。由于您的目标是纯粹的内存映射,因此您可能不想回滚任何复杂的多步骤操作。如果您将访问包装在互斥锁中,那么您就是线程安全的。如果这样一个受互斥体保护的 std::map 还不够,你还想做什么?
-
我希望能够中途完成数据库的突变,达到错误条件,然后撤消迄今为止发生的所有更改,以便数据库保持一致。如果用户要求我的程序以不允许的方式更改对象,则会出现错误情况。我真的不想在每次突变之前都经过单独的验证阶段。
-
@David:它应该是多线程的吗?