2015-12-23 51 views
0

我有一个设计问题。考虑在多个集群环境中运行的应用程序,可以说有3个集群。应用程序侦听目录,并处理所有导出的新文件并将其发送到文档管理系统。我只想要一个集群处理给定的文件,这样我就可以避免竞争条件。为此,我创建了一个名为DocumentLock的锁表,以便我可以使用数据库作为仲裁者。这3列是guid(主键),文件ID(这是来自文件的唯一名称),锁定时间戳。我正在使用Spring事务,并将Oracle作为数据库。我打算使用Read_Committed隔离级别。春季交易和插入数据库

因此,假设集群A获取文件A,同时集群B也获得文件A的保存。现在,使用事务A的集群A将尝试插入到DocumentLock表中,并且可以说它是成功的。所以我将在DocumentLock表中有1行,唯一的ID是文件A(文件名)。现在,同时使用Tx-B的集群B尝试向DocumentLock表中插入一条记录,但由于我使用'Read_Committed'隔离级别,因此需要等到Tx-A提交。因此TX-B将等待州。一旦Tx-A被提交,现在Tx-B将尝试插入相同的记录(文件A),并且因为它违反了唯一性约束,它将引发错误。

我对Read_committed的理解是否正确?

我试图避免多个集群在表中插入相同的文件(唯一记录),所以我假设如果两个事务开始同时插入相同的文件名,其中一个需要等到另一个一个是承诺?那么Oracle如何决定哪个事务(Tx-A或Tx-B)获得表(锁)?还有Read_committed,整个表是锁定的,还是只是行?

另外,如果不同的文件集B中获取的举行,说文件B应该插入没有任何问题的DocumentLock,为群集A是处理文件A和集群B需要处理的文件B. 感谢您的帮助

回答

1

我正在提供替代方法来解决这个问题。

将隔离级别设置为READ UNCOMMITTED。这将确保任何未提交的数据库更新也可以由其他事务准备好。这种方法的好处是,从一个群集插入数据库的任何内容都可以立即被所有其他群集访问。通过这种方式,人们可以通过一些应用程序逻辑来确定谁应该获得锁定。

让我们来看看案例。

案例1:群集A和B都试图在文件f获得锁

  • 集群A想冒头文件的F.

  • 集A在搜索数据库,看看是否有一个已经得到了锁定。

  • 集群A收到文件F的保持和记录插入到表中, 但它并没有犯

  • 集B要采取文件的第F.

  • 集B的交易在数据库中进行搜索并查找由群集A
    插入的条目,即使未提交该条目也是如此。

案例2:群集A和B都试图让文件F1和F2

  • 集群A要采取文件F1的保持锁。
  • 集群A在数据库中搜索,看看是否有人已经获得锁定。
  • 集群A获取文件F1并将记录插入表 但它没有提交事务
  • 集群B想抓住文件F2。
  • 集群B在数据库中搜索,看看是否有人已经获得锁定。
  • 集群B获取文件F2并将记录插入表 但它没有提交事务。
  • 集群A和集群B提交事务。

我不确定插入File f记录是否没有被集群A提交,在这种情况下,如果集群B也插入文件f的记录,数据库将抛出唯一性错误。所以这个解决方法来检查应用程序逻辑中的所有内容可以提供帮助。

+0

感谢您的回答。对于案例1,如果由于某种原因事务A被回滚,并且集群B认为集群A处理了文件F1。这不是脏读的经典案例吗? –

+0

如果你正在做一些处理这些文件的事情。您的群集逻辑应该再次遍历文件列表以确定是否有任何文件需要处理。在上面提到的Dirty Read的情况下,集群B在再次尝试循环文件时应该得到文件F.应该有一些连续的轮询方法来查找未处理的文件。这种方式会在下次轮询中处理脏读。 –

+0

这是有道理的。谢谢 –