首页 > 解决方案 > SQL中进程间数据如何同步?

问题描述

我想知道一些可能非常愚蠢的事情,但我似乎找不到答案(通常这不是一个好兆头)。假设我们有一个 SQL 服务器(MySQL、PostgreSQL,尽管没有服务器,这个问题甚至适用于 Sqlite3)和几个连接到它的客户端。我已经看到无数次在我看来可能难以同步的查询。
所以让我们假设我们有一个每天有一行的表(例如使用统计)。

statistic (
    day,
    num_requests
)

(我避免提及数据类型,因为这不是重点,但请求的数量应该是某种数量。)

所以当一个新的 web 请求被发送时,web 服务器会询问这个表的当前统计信息并增加请求的数量。没有大佬吧?

number = cursor.execute("""
        SELECT num_requests FROM statistic
        WHERE ...
""")
number += 1
cursor.execute("""
        UPDATE statistic SET num_requests=?
        WHERE ...
""", (number, ))

但是如果两个请求同时处理,可能是在几个客户端上,会发生什么?不同的流程?他们每个人都询问今天的当前统计信息(只是一个读取操作,非阻塞),他们从该行获取请求数(此步骤不涉及服务器),然后将其递增 1。此时,如果两个请求在某种程度上同时运行,它们都增加了一次相同的数字,并且它们发送UPDATE带有它们的数字的请求。

最后,今天统计的请求数量增加了一个,尽管它们是两个请求。我知道有一些机制可以确保正确的数据同步,但我看不出它如何解决这种情况。据我所知,读取通常是非阻塞的。写入可以是阻塞的,但由于之前已经发生过其他进程的读取,因此第二次写入操作将不可接受。而且我看不出有任何方式可以逻辑地表达这一点。

换句话说,这似乎是我们在大多数编程语言中锁定行的地方,并说“从那时起,你既不能读也不能写,我正在努力”。第一个请求将执行其读取(锁定)、递增和写入,然后解锁。第二个请求必须耐心等待锁被释放。我在 SQL 中看不到这种机制。那是透明的,甚至没有必要吗?如果是这样,它是如何工作的?还是我们一生都面临着类似的问题?

谢谢!

标签: sql

解决方案


cursor.execute("""
    UPDATE statistic SET num_requests=num_requests+1
    WHERE ...
""", (number, ))

推荐阅读