Sau*_*abh 0 postgresql multithreading transactions
我知道 PostgreSQL 使用 MVCC 来处理并行事务,但我不确定在以下场景中会发生什么:
Client1 Client2 Time
-------------------------------------------------------------------
BEGIN BEGIN time=t0
Update row where id=1 Update row where id=1 time=t1
COMMIT COMMIT time=t2
Run Code Online (Sandbox Code Playgroud)
两个客户端都将在时间=t0 时启动事务,在时间=t1 时更新各自快照中 id=1 的同一行,并在时间=t2 时提交事务。由于提交是在同一时刻(时间=t2)完成的,它们是并行执行还是由 PostgreSQL 顺序执行?如果它们并行运行,是否有数据损坏的可能?谢谢。
编辑:“COMMIT”与 libPQ 一起使用。在 psql 中,COMMIT = END。
这篇文章充满了误解。
这里不涉及线程,所以它根本不是“线程安全”的。PostgreSQL 使用多个进程,每个连接一个进程。客户端应用程序可能不会在线程之间共享单个连接,除非它们确保执行适当的锁定以阻止多个线程同时使用该连接。
你问的是并发性,而不是线程。而且您并不是真正询问“线程安全”,而是询问原子性和隔离性。请参阅 PostgreSQL 文档中有关并发控制的章节。
在这种情况下:
READ COMMITTED
每个后续语句都会获得自己的快照UPDATE
s 都会影响同一行。他们将锁定该行,并且一个将等待另一个提交或回滚。届时,等待的一方将重新检查其WHERE
子句是否仍然匹配,然后继续进行自己的更改。COMMIT
和BEGIN
这里的都是噪音,它们并不重要,因为如果您单独运行语句,它们会自动包装在单语句事务中。所以
由于提交是在同一时刻完成的(时间=t2)
它们不能完全相同地完成,因为它们需要短暂的锁定来更新某些共享内存数据结构并写入事务日志。但它们确实重叠。从逻辑上讲,一个人仍然先于另一个人做出承诺。
您似乎认为声明只有在您提交时才会生效。这不是真的。语句会立即运行,因此这些 UPDATE 在您发送后立即运行。在提交之前,这些更改对其他事务不可见。
如果它们并行运行,是否有数据损坏的可能?
不,这就是 PostgreSQL 和其他 RDBMS 的全部意义。不会出现数据损坏。
在这种情况下,两个 UPDATE 将使用行锁定在它们之间进行排序。如果您在两个并发会话中完全尝试在这里所做的事情,但不提交它们,那么查询pg_locks
您将看到一个正在等待另一个。
可能会出现与串行而不是同时运行两个事务所发生的结果不同的结果。PostgreSQL 文档的事务隔离章节对此进行了详细讨论和示例。
事务并不是让您忽略并发问题的神奇秘方。如果您使用SERIALIZABLE
事务,它们离它不会太远,但您的应用程序必须准备好重试任何事务,因为它们随时可能由于序列化失败而失败。(不过,编写良好的应用程序无论如何都可以做到这一点,因为即使是READ COMMITTED
xacts 也可能由于死锁等原因而失败)。
归档时间: |
|
查看次数: |
4178 次 |
最近记录: |