在使用LiveServerTestCase和Selenium测试Django / Postgres应用程序时,我看到间歇性的死锁问题。 LiveServerTestCase继承自TransactionTestCase,因此在每次测试运行后都会截断所有数据库表。但有时截断会导致死锁,因为其中一个表被未解析的Postgres事务锁定。我可以看到,因为此查询返回一行:
select * from pg_stat_activity
where datname='test' and current_query='<IDLE> in transaction';
因此,我的应用程序中的某些活动必须创建一个未解析的事务。我已经梳理了测试,以确保他们在退出之前等待任何更新完成,并确信不是它。
查看Postgres日志,我经常看到这两行,没有相应的COMMIT
或ROLLBACK
:
SHOW default_transaction_isolation
BEGIN
我怀疑这些导致了僵局。知道什么可能发布这个SQL或如何禁用它?这是Django 1.5。
答案 0 :(得分:2)
这种死锁的根本原因是Django 1.5的自动提交行为。默认情况下,Django 1.5使用打开的事务运行,如果您执行COMMIT
或UPDATE
,则只会被INSERT
关闭。 &#34;读&#34;操作(SELECT
)导致我上面提到的无法匹配的BEGIN
语句。如果SELECT
恰好在测试结束TRUNCATE
之前发生,则会出现死锁。为避免死锁,测试必须在所有请求完成后才退出,即使请求不会导致DB写入。如果Ajax调用在更新后异步更新页面的某些部分,那可能会很棘手。
更好的解决方案是使用Django 1.6,其中atomic()
是唯一(不推荐)的事务创建原语。它不会为读取操作打开事务,也不会留下悬空BEGIN
语句。测试可以遵循不退出的常识方法,而#34;写&#34;请求待定。