aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2002-08-11 00:08:48 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2002-08-11 00:08:48 +0000
commit2e10863bf52797a7a285271677e3f2c35a376f20 (patch)
tree679e61f03d46e55c3b8d41a6fd6fd43002f04d13
parent5c3102d6d1fe85c68759480e88703d49780e1783 (diff)
downloadpostgresql-2e10863bf52797a7a285271677e3f2c35a376f20.tar.gz
postgresql-2e10863bf52797a7a285271677e3f2c35a376f20.zip
Now that we allow ANALYZE to run inside a transaction block, the locks
it takes could be held for quite awhile after the analyze step completes. Rethink locking of pg_statistic in light of this fact. The original scheme took an exclusive lock on pg_statistic, which was okay when the lock could be expected to be released shortly, but that doesn't hold anymore. Back off to a normal writer's lock (RowExclusiveLock). This allows concurrent ANALYZE of nonoverlapping sets of tables, at the price that concurrent ANALYZEs of the same table may fail with 'tuple concurrently updated'.
-rw-r--r--src/backend/commands/analyze.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/src/backend/commands/analyze.c b/src/backend/commands/analyze.c
index 5cabe21d5f9..5dafb1a42ad 100644
--- a/src/backend/commands/analyze.c
+++ b/src/backend/commands/analyze.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.41 2002/08/05 03:29:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/analyze.c,v 1.42 2002/08/11 00:08:48 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -272,7 +272,7 @@ analyze_rel(Oid relid, VacuumStmt *vacstmt)
*/
if (attr_cnt <= 0)
{
- relation_close(onerel, NoLock);
+ relation_close(onerel, AccessShareLock);
return;
}
@@ -1644,6 +1644,15 @@ compare_mcvs(const void *a, const void *b)
* This could possibly be made to work, but it's not worth the trouble.
* Note analyze_rel() has seen to it that we won't come here when
* vacuuming pg_statistic itself.
+ *
+ * Note: if two backends concurrently try to analyze the same relation,
+ * the second one is likely to fail here with a "tuple concurrently
+ * updated" error. This is slightly annoying, but no real harm is done.
+ * We could prevent the problem by using a stronger lock on the
+ * relation for ANALYZE (ie, ShareUpdateExclusiveLock instead
+ * of AccessShareLock); but that cure seems worse than the disease,
+ * especially now that ANALYZE doesn't start a new transaction
+ * for each relation. The lock could be held for a long time...
*/
static void
update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
@@ -1651,12 +1660,7 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
Relation sd;
int attno;
- /*
- * We use an ExclusiveLock on pg_statistic to ensure that only one
- * backend is writing it at a time --- without that, we might have to
- * deal with concurrent updates here, and it's not worth the trouble.
- */
- sd = heap_openr(StatisticRelationName, ExclusiveLock);
+ sd = heap_openr(StatisticRelationName, RowExclusiveLock);
for (attno = 0; attno < natts; attno++)
{
@@ -1789,6 +1793,5 @@ update_attstats(Oid relid, int natts, VacAttrStats **vacattrstats)
heap_freetuple(stup);
}
- /* close rel, but hold lock till upcoming commit */
- heap_close(sd, NoLock);
+ heap_close(sd, RowExclusiveLock);
}