跨数据库会话保持多用户状态

Keeping multi-user state across DB sessions

情况

假设我们有一个连接到 (Postgre)SQL 数据库的 Web 应用程序,其任务可以概括为:

  1. 一个 SELECT 操作来可视化数据。
  2. 一个 UPDATE 操作,根据可视化数据存储修改。

简单,但是...所涉及的数据不是特定于用户的,因此其他用户可能会在此过程中更改它。编辑任务可能需要很长时间(可能超过一个小时),这意味着这些冲突发生的可能性不低:对问题实施稳健的解决方案是有意义的。

方法

想法是,一旦用户尝试提交更改(即触发 UPDATE 操作),将触发大量数据库检查以确保所涉及的数据在与此同时。

假设我们为数据的每次更改都添加了时间戳,这就像在数据被 SELECTed 时保持访问时间一样简单,并确保在该时间之后没有对所涉及的数据进行新的更改.

问题

我们可以很容易地在用户执行编辑时将访问时间保留在前端应用程序中,然后在执行 UPDATE 时将其作为参数提供给触发器函数,但这对于安全性来说是不可取的原因。数据库应该存储用户的访问时间。

一个直观的解决方案可能是 TEMPORARY TABLE 关联到数据库会话。但是,同样,用户可能会花费很长时间来完成这项任务,因此从池中捕获连接并使其长时间保持空闲似乎也不是一个好的选择。 SELECTUPDATE 操作将在不同的会话下执行。

问题

是否有任何范例或规范的方法来有效地处理和解决这个问题?

这个问题被称为 "lost update" 问题。

有几种解决方案取决于是否使用连接池以及使用的transaction isolation level

  1. 悲观锁定 SELECT ... FOR UPDATE without connection pool
  2. 如果使用连接池,则使用时间戳列进行乐观锁定。