gpt4 book ai didi

python - zodb:数据库冲突失败

转载 作者:搜寻专家 更新时间:2023-10-30 22:17:21 25 4
gpt4 key购买 nike

我有一个服务器和一个客户端。

客户端发送请求。该请求有一个与之关联的特定键,例如a-1, a-2, b-1, b-4.

如果同时传入两个对同一个键的请求,则会出现冲突错误,因为正在修改相同的数据结构。

我可以让客户端简单地不同时发送同一个 key 的两个请求。但是,我希望这个系统也能与多个客户一起工作。让客户端协调它们发送给服务器的内容似乎很愚蠢。相反,如果某个键已经被修改,我希望服务器简单地阻止对某个键的请求,直到完成具有相同键的其他请求。

为此,我创建了一个锁定系统。在服务器上的函数开始时,我执行以下操作:

key = ...
print "Acquiring %s lock..." % (key,)
KEY_LOCKS[key].acquire()
print "%s lock acquired." % (key,)
def after_commit_hook(success):
KEY_LOCKS[key].release()
print "(after %s commit): Released %s lock" % (('failed', 'successful')[success], key)
transaction.get().addAfterCommitHook(after_commit_hook)

其中 KEY_LOCKS 是一个将键映射到 threading.Lock 的字典。之后是修改持久数据结构的代码。

我假设会发生的是,如果一个请求进入一个已经被处理的 key ,它会在获取锁时阻塞。只有当较早的请求已经提交(从而排除任何冲突错误)时,新请求才会恢复。在获取锁之前,请求不会执行任何会发生冲突的操作。

大多数请求工作正常:

Acquiring a-b lock...
a-b lock acquired.
(after successful commit): Released a-b lock
Acquiring a-c lock...
a-c lock acquired.
(after successful commit): Released a-c lock

然而,当发送相同的 key 时,仍然存在问题,即使锁定似乎有效:

Acquiring q-q lock...
q-q lock acquired.
Acquiring q-q lock...
(after successful commit): Released q-q lock
q-q lock acquired.
(after failed commit): Released q-q lock
repoze.retry retrying, count = 1
Traceback (most recent call last):
...
ConflictError: database conflict error (oid 0x13009b, class persistent.list.PersistentList)

然后请求重试。请注意,q-q 锁 仅在成功提交后才获取。

什么给了?为什么这个系统不能防止冲突错误?我的假设哪里不正确?


编辑:好吧,如果在 transaction.get().addAfterCommitHook(after_commit_hook) 行之前我放置了 transaction.begin(),它就可以工作。对于我的生活,我无法弄清楚为什么。在 transaction.begin() 行之前,我的全部代码是:

post = request.params
if not post: return Response("No data!")

data = eval(post['data'])
time_parsed = time.time()
my_app = request.context

这解决了我的问题,但我没有把它作为答案,因为我仍然想知道:如果我之前没有开始新的交易,为什么会出现冲突错误?

最佳答案

从事务开始的那一刻起,ZODB 就提供了具有一致 View 的连接。这意味着最重要的是,在新事务开始之前,一个线程不会看到其他线程在数据库中所做的更改!这是名为 Multiversion Concurrency Control 的数据库的基本特征.

换句话说,如果你希望你的应用程序线程不通过使用锁发生冲突,你还需要在锁可用时启动一个新的事务。

在我看来,锁定是您想要避免的性能瓶颈。持有锁的时间越长,遇到不一致数据的可能性就越大(您的起始状态与数据库状态)。

在 Zope 中,使用了一种乐观的方法:当出现冲突错误时,事务被中止,并从头开始重新尝试。如果您的事务是短而快的事务,则可以避免大多数锁定问题,而只要持久性更改发生更改导致冲突,您只需重新计算对数据库的更改。

关于python - zodb:数据库冲突失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9810116/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com