select和truncate之间的死锁(postgresql)

select和truncate之间的死锁(postgresql),postgresql,deadlock,Postgresql,Deadlock,表输出值\u 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 data

表输出值\u 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"
显然,如果只看上面链接的手册页,不清楚为什么查询父表会影响其子表。SELECT命令手册页的以下摘录对此进行了澄清:


我会在截短的伪代码中尝试:

#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;
  };
};
这样您就不会出现死锁,因为父表将被独占锁定。用户在执行truncate运行时只会阻塞一小部分秒,并在提交后自动恢复


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

您能从该错误消息中展开关系ID吗?i、 e.选择2494865::regclass等。谢谢,问题比答案更有用,在查看关系id后,我了解问题在哪里: