diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2002-08-11 00:08:48 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2002-08-11 00:08:48 +0000 |
commit | 2e10863bf52797a7a285271677e3f2c35a376f20 (patch) | |
tree | 679e61f03d46e55c3b8d41a6fd6fd43002f04d13 | |
parent | 5c3102d6d1fe85c68759480e88703d49780e1783 (diff) | |
download | postgresql-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.c | 23 |
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); } |