2010-05-19 782 views
0

output_values_center1(和其他)继承output_values。我定期截断表output_values_center1并加载新数据(在一个事务中)。那时用户可以请求一些数据,并且他收到错误信息。为什么它发生(选择查询请求只有一条记录),以及如何避免这样的问题:select和truncate之间的死锁(postgresql)

2010-05-19 14:43:17 UTC ERROR: deadlock detected 
2010-05-19 14:43:17 UTC DETAIL: Process 25972 waits for AccessShareLock on relation 2495092 of database 16385; blocked by process 26102. 
    Process 26102 waits for AccessExclusiveLock on relation 2494865 of database 16385; blocked by process 25972. 
    Process 25972: SELECT * FROM "output_values" WHERE ("output_values".id = 122312) LIMIT 1 
    Process 26102: TRUNCATE TABLE "output_values_center1" 
+1

你可以从这个错误消息中扩展出关系ID吗?即'选择2494865 :: regclass'等。 – araqnid 2010-05-19 18:24:53

+0

谢谢你,问题是更有用然后回答,后看关系id我明白哪里是问题:) – valodzka 2010-05-20 16:36:34

回答

1
0

我想尝试这个(在伪代码)用于截断:

#define NOWAIT_TIMES 100 
#define SLEEPTIME_USECS (1000*100) 
for (i=0; ; i++) { 
    ok = query('start transaction'); 
    if (!ok) raise 'Unable to start transaction!'; 
    queries = array(
    'lock table output_values in access exclusive mode nowait', 
    'truncate output_values_center1', 
    'commit' 
); 
    if (i>NOWAIT_TIMES) { 
    // we will wait this time, as we tried NOWAIT_TIMES and failed 
    queries[0] = 'lock table output_values in access exclusive mode'; 
    } 
    foreach q in queries { 
    ok = query(q); 
    if (!ok) break; 
    } 
    if (!ok) { 
    query('rollback'); 
    usleep(SLEEPTIME_USECS); 
    } else { 
    break; 
    }; 
}; 

这种方式,你将会很安全从死锁,因为父表将被独占锁定。用户将在截断运行时阻塞几分之一秒,并在提交后自动恢复。

但要做好准备,这可以在繁忙的服务器上运行几秒钟,因为当表正在使用时,锁将失败并被重试。