在我的Apache Tomcat服务器上,我有一个OpenRDF Sesame triplestore来处理与用户和文档相关的RDF三元组以及这些实体之间的双向链接:
http://local/id/doc/123456 myvocabulary:title "EU Economy"
http://local/id/doc/456789 myvocabulary:title "United States Economy"
http://local/id/user/JohnDoe myvocabulary:email "john@doe.com"
http://local/id/user/JohnDoe myvocabylary:hasWritten http://local/id/doc/123456
用户John Doe用电子邮件“john@doe.com”编写的“欧盟经济”一书的三重状态。
在多个客户端上运行的Java应用程序通过HTTPRespository使用此类服务器来插入/更新/删除此类三元组。
问题来自并发连接。如果Java客户端删除书籍“456789”并且另一个客户端同时将同一本书链接到“John Doe”,则可能存在“John Doe”链接到不再存在的书籍的情况。
为了找到解决方案,我做了两笔交易。第一个是(T1):
(a)检查书籍是否存在(即“456789”)。
(b)如果是,请将给定的资料(即“JohnDoe”)与本书联系起来。
(c)如果否,则返回错误。
第二个是(T2):
问题是如果序列是(T1,a)(T2,d)(T1,b)(T1,c),则会出现一致性问题。
我的问题是:如何处理锁定(如MySQL FOR UPDATE或GET_LOCK)以正确隔离芝麻这样的交易?
答案 0 :(得分:2)
较旧版本的Sesame(2.7.x及更早版本)不支持HTTP上的事务隔离。在HTTP连接中,事务只是在客户端一起批量操作,但是没有从服务器获得锁定,因此在这种情况下无法控制隔离。
因此,在较旧的芝麻版本中处理此问题的唯一方法是在查询中保持健壮,而不是依赖于完整的数据一致性(无论如何,这在无模式/半结构化数据范例中是一个奇怪的概念) 。例如,在这种特殊情况下,请确保在查询链接到配置文件的图书时,图书数据实际上就在那里 - 不要仅仅依赖于参考。
但是,在Sesame 2.8及更新版本中,可以通过HTTP获得完整的事务隔离支持,并且还可以基于每个事务对精确的事务隔离级别进行额外控制。锁定方案取决于您使用的特定triplestore实现。
Sesame的本机存储使用乐观锁定,这意味着它假定一个事务能够进行它想要的更新,并在发生冲突时抛出异常。设置事务的隔离级别控制存储如何处理并发事务的锁定。 Sesame Programmers manual有关于事务处理和可用隔离级别的更多详细信息。本机存储上事务的默认隔离级别为SNAPSHOT_READ
。
对于您的示例事务:在默认隔离级别中,T1和T2都会观察商店的查询一致快照,并在草图中显示序列:T1看到图书存在,因此将其添加到配置文件,T2可以删除它。最终结果将是配置文件链接到不存在的书籍 - 但实际上,这在技术上并不是不一致的,因为T2不会对配置文件中是否使用特定书籍进行任何验证。无论您使用哪种事务隔离级别,如果在您的方案T2中在 T1之后执行,最终结果将是指向不存在的书籍的链接。如果您想确保无法进入这种情况,则需要扩展T2以检查要删除的书是否未链接到配置文件,并使隔离级别SNAPSHOT
或{{1 }}。