postgres中的锁定机制/ postgres中的死锁。 [我正在使用sqlalchemy]

时间:2016-01-05 04:09:25

标签: python postgresql sqlalchemy flask-sqlalchemy database-deadlocks

我对sqlalchemy-psql中的锁定机制如何工作完全感到困惑。 我正在运行一个带有sqlalchemy和postgres的python-flask应用程序。由于我有多个线程处理一些数据并在psql上更新它,我得到以下死锁:

  

2015-12-31 17:[ERROR](由于Query-invoked autoflush引发;考虑使用session.no_autoflush阻止,如果此刷新过早发生)(psycopg2.extensions.TransactionRollbackError)检测到死锁

     

详细信息:进程22833在事务14114188上等待ShareLock;被进程阻止19759。

     

流程19759在交易14114189上等待ShareLock;被程序22833阻止。

这是否会出现僵局:

Thread 1                                       Thread 2                                   
| (start an sqlalchemy session)                |
 db.session()                                  db.session()
|(Using sqlalchemy)                            |
Update row1 of table1                          Update row2 of table 1
|                                              |
Update row2 of table1                          Update row1 of table1
|                                              |  
session.commit()                               session.commit()

Here是我的问题的一些答案,但我无法将它们与sqlalchemy联系起来。

1 个答案:

答案 0 :(得分:3)

在PostgreSQL中,行会在更新时被锁定 - 实际上,这实际上的工作方式是每个元组(行的版本)都有一个名为xmin的系统字段,用于指示哪个事务使该元组成为当前(通过插入或更新)和一个名为xmax的系统字段,以指示哪个事务已过期该元组(通过更新或删除)。当您访问数据时,它会检查每个元组,以确定您的事务是否可见,方法是根据这些值检查您的活动“快照”。

如果您正在执行UPDATE并且与您的搜索条件匹配的元组具有xmin,这将使您的快照和活动事务的xmax可见,它将阻塞,等待该事务完成。如果首次更新元组的事务回滚,则事务会唤醒并处理该行;如果第一个事务提交,则事务会唤醒并根据当前事务隔离级别采取操作。

显然,死锁是以不同顺序发生在行中的结果。 RAM中没有行级锁定,可以同时为所有行获取,但如果行以相同的顺序更新,则无法进行循环锁定。不幸的是,建议的IN(1,2)语法并不能保证这一点。不同的会话可能有不同的成本因素活动,后台“分析”任务可能会更改一个计划的生成与另一个计划之间的表的统计信息,或者它可能正在使用seqscan并受PostgreSQL优化的影响,导致新的seqscan加入一个已在进行中并“循环”以减少磁盘I / O.

读这个     http://elioxman.blogspot.in/2013/02/postgres-deadlock.html