2015-09-06 34 views
0

我必须为使用Postgres for database的非常高流量的Web应用程序编写SQL事务。控制并发读取然后更新然后在Postgres中写入事务

我的问题是如何控制READ THEN UPDATE THEN WRITE事务的并发性,如果两个用户同时进行该事务?

对于高流量的Web应用程序,最佳做法是什么?任何帮助/建议将非常感激。

在此先感谢。

+0

https://wiki.postgresql.org/wiki/Performance_Optimization –

+0

你能更具体的了解,究竟是什么,您可以通过“读,然后更新,然后写上”是什么意思?你的意思是通过应用程序进行读 - 修改 - 写吗? –

+0

嗨克雷格,是我的意思是通过应用程序中的读 - 修改 - 写。 – John

回答

4

解释性说明:我假设您的意思是read-modify-write工作负载,并且“READ THEN UPDATE THEN WRITE”的大写字母并不意味着表示某些特殊事务选项SQL语法来自我不熟悉的产品。

如果你的web应用正在做读 - 修改 - 写高并发和流量的循环,那么你就不能使用传统的行锁定:

  • BEGIN
  • SELECT primarykey, col1 FROM thetable WHERE ... FOR UPDATE
  • 过程中的应用
  • UPDATE blah SET col1 ... WHERE primarykey ...
  • COMMIT

因为用户“思考时间”和网络延迟可能是无限的。大多数连接将在“应用程序中的过程”阶段中停留无限期。每个等待会话意味着一个开放的空闲事务,这意味着有限的数据库资源,如连接限制和内存消耗。

传统的,完善的解决方案是使用optimistic concurrency control,有时误导性地称为乐观锁定。一些ORM在本地支持。如果您直接使用SQL或通过不支持的框架,那么实现它就很容易。其原理是,你的逻辑流程大致如下:

  • BEGIN READ ONLY TRANSACTION
  • SELECT primarykey, col1, row_version FROM thetable WHERE ...
  • COMMIT
  • 过程中的应用,并等待用户响应
  • BEGIN
  • UPDATE blah SET col1 ..., row_version = row_version + 1 WHERE primarykey ... AND row_version = 'prev_row_version'
  • 检查是否有UPDATE使用影响由数据库中UPDATE响应
    • 返回如果它影响了零行受影响的行数的任何行,则WHERE条款不相符,暗示别人更新的行,因为我们SELECT编它。回到开始并重新开始。
    • 如果它影响到一行,我们知道没有人打我们来更新这一行,所以COMMIT并告诉用户一切正常。

框架如Hibernate通过注释列作为行版本的自动支持这一点。

乐观并发控制可以与传统的锁定和适当的数据库触发器进行互操作。参见例如the sample trigger I wrote for Hibernate inter-operation

相关问题