对象图和 READ_COMMITTED 事务隔离

发布于 2024-10-21 18:40:05 字数 884 浏览 1 评论 0原文

警告:几年前我遇到了这个问题。我忘记了我试图解决的实际问题,所以我用涉及链表的理论问题代替了它。


我已经尝试使用 READ_COMMITTED 事务隔离级别一年多了,但我对由于缺乏经验而产生的错误感到非常沮丧。如果你们能提醒我我在这里缺少什么,我将不胜感激。

我实现的几乎所有应用程序逻辑都无法用单个 SQL 查询来表达。也就是说,我几乎总是最终不得不遍历对象图。我不可避免地会在同一事务中遇到不一致的状态。例如,假设您在数据库中存储一个单链表,并且您想要查明该列表是否包含循环(下面将更详细地描述)。我想不出任何方法可以在 READ_COMMITTED 下执行此操作,因为当我在图表中行走时,可以从我的脚下更新出站引用。我只能看到 READ_COMMITTED 工作适用于可以使用单个 SQL 语句表示的查询。

  • 数据库模式是Node[id, name, next_id]
  • 最初数据库包含:A -> B-> C->一个

    1. 线程 1 读取:A -> BB -> C
    2. 线程 2 将数据库更新为:D -> B-> C-> D
    3. 线程 1 读取:C -> D
    4. 线程 1 没有检测到循环,尽管应该检测到循环。从线程 1 的角度来看,它是: A -> B-> C-> D 但它应该检测到以下循环之一:

A -> B-> C->一个或 <代码>D - > B-> C-> D

CAVEAT: I ran into this problem a few years ago. I forget the actual problem I was trying to solve so I have substituted it with a theoretical problem involving a linked list.


I've been trying to use READ_COMMITTED transaction isolation level for over a year now and I'm getting very frustrated with the bugs resulting from my lack of experience. I would appreciate it if you guys could give me a head's up as to what I am missing here.

Pretty much all application logic I implement cannot be expressed in terms of a single SQL query. That is, I almost always end up having to walk the object graph. Inevitably I run into inconsistent state from within the same transaction. For example, imagine you store a singly-linked list in the database and you want to find out whether the list contains a loop (described in greater detail below). I can't think of any way to do this under READ_COMMITTED because the outbound references could be updated from underneath my feet as I walk the graph. I can only see READ_COMMITTED working is for queries which can be represented using a single SQL statement.

  • The database schema is Node[id, name, next_id]
  • Initially the database contains: A -> B -> C -> A

    1. Thread 1 reads: A -> B, B -> C
    2. Thread 2 updates the database to: D -> B -> C -> D
    3. Thread 1 reads: C -> D
    4. Thread 1 detects no loop although one should have been detected. From Thread 1's point of view it read: A -> B -> C -> D but it should have detected one of the following loops:

A -> B -> C -> A or
D -> B -> C -> D

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

盛装女皇 2024-10-28 18:40:05

由 Michal Bergmann 提供的回答:http://groups.google .com/group/h2-database/browse_frm/thread/8f253177e2b6c543?tvc=1

READ_COMMITTED_SNAPSHOT隔离级别可以帮助您解决问题
与并发操作。它允许执行多个查询
不受其他同时发生的事务的影响。

你也可以

  • 先将数据复制到临时表
  • 锁定表并阻止更新
  • 监视表的变化(使用触发器)以及是否发生变化
    在循环检测期间,您的结果可能无效,那么您可以
    扔掉它并重复循环检测。
  • 使用应用程序逻辑推迟任何更改,直到循环检测完成
    完成

使用 READ_COMMITTED_SNAPSHOT 隔离级别可能是最好的
解决方案,如果数据库支持的话。它的开销很低,并且不
阻止并发事务。

Answer courtesy of Michal Bergmann: http://groups.google.com/group/h2-database/browse_frm/thread/8f253177e2b6c543?tvc=1

READ_COMMITTED_SNAPSHOT isolation level can help you to solve problem
with concurrent operations. It allows to performing multiple queries
without being affected by other simultaneous transactions.

You could also

  • copy data to temporary table first
  • lock the table and prevent updates
  • monitor table for changes (with a trigger) and if it does change
    during loop detection, your result may not be valid, then you can
    throw it away and repeat loop detection.
  • use application logic to postpone any changes till loop detection is
    finished

Using READ_COMMITTED_SNAPSHOT isolation level is probably the best
solution, if database supports it. It has low overhead and doesn't
block concurrent transactions.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文