select和truncate之间的死锁(postgresql)

时间:2010-05-19 15:29:44

标签: postgresql deadlock

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

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"

2 个答案:

答案 0 :(得分:1)

答案 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;
  };
};

通过这种方式,您可以安全地避免死锁,因为父表将被独占锁定。用户将在截断运行时阻塞一小部分秒,并在提交后自动恢复。

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