锁定postgres交易

时间:2016-05-30 09:54:03

标签: node.js postgresql sequelize.js

我正在加载测试我的node.js应用程序。在某些时候,我到达请求待处理的状态,我最好的猜测是因为锁定了事务。这是最后一条日志声明:

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

pg_lock中我通过以上查询获得了4行,GRANTED = truemode ExclusiveLock

我应该从哪里开始寻找错误? 如果我在此锁定请求中进行了大量insertupdate操作,那么隔离级别应为REPEATABLE READ吗? 有没有办法调试/处理这种情况? 是否有任何机制可以超时锁定,以便可以轻松/自动释放应用程序并且不会阻止进一步的请求?

附带问题(因为我没有直接寻找工具):是否有任何工具可以监控并发现这种情况? (我希望使用Munin。)

我使用nodejs 4.2.1 with express 4.13.3,sequelize 3.19.3 as Postgres 9.4.1 ORM。

2 个答案:

答案 0 :(得分:2)

欢迎使用PostgreSQL事务锁地狱:)

您可以花费大量时间来确定锁定的确切位置以及原因。但它很有可能帮助你解决问题。

解决此类情况的一般方法如下:

  • 将您的交易规模保持在应用程序业务逻辑所需的最低限度。例如,避免使用相同类型的插入或更新,将其替换为多行类似物,因为查询IO很昂贵
  • 在执行仅修改数据的单个查询时不要使用事务,即避免不必要的事务。
  • 实现可以确定事务锁定并提供执行事务的重复尝试的错误处理。记录此类重复将帮助您了解系统的弱点以及如何更好地重新设计它。

即使在精心设计的系统中,最后一步也常常成为必需品,不要让它吓到你;)

答案 1 :(得分:0)

我遇到了类似的情况,我开始请求相同的更新锁定的5个并行事务,第一个也继续需要更多postgres调用的工作。整个系统死锁,第一个事务在pg_stat_activity中的事务中列为空闲状态,并被授予对pg_locks中请求的所有锁的访问权限。

我认为发生了什么;

第一个事务获得了锁定,然后完成了查询。在此之后,它断开了与postgres的连接。

以下4个事务分别打开一个连接并锁定锁,这是由第一个事务持有的。

由于它们被阻止,第一个事务将被执行,当它尝试连接到postgres进行查询时,它会死锁,因为sequiezlize已经用完了连接。

当我更改了sequiezlize初始化并添加了更多连接到池时,默认为5,死锁消失。

我不确定是谁在使用第5个连接,或者由于某种原因,默认情况下是4而不是5,但似乎仍然勾选所有方框。

另一个解决方案是在postgres中使用NOWAIT选项,因此在请求锁定而不是获取锁定时,事务会中止,具体取决于您的用例。

希望如果其他人遇到同样的问题会有所帮助。