1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-17 17:02:08 +03:00

Make DDL operations play nicely with Serializable Snapshot Isolation.

Truncating or dropping a table is treated like deletion of all tuples, and
check for conflicts accordingly. If a table is clustered or rewritten by
ALTER TABLE, all predicate locks on the heap are promoted to relation-level
locks, because the tuple or page ids of any existing tuples will change and
won't be valid after rewriting the table. Arguably ALTER TABLE should be
treated like a mass-UPDATE of every row, but if you e.g change the datatype
of a column, you could also argue that it's just a change to the physical
layout, not a logical change. Reindexing promotes all locks on the index to
relation-level lock on the heap.

Kevin Grittner, with a lot of cosmetic changes by me.
This commit is contained in:
Heikki Linnakangas
2011-06-08 13:47:21 +03:00
parent 16925c1e1f
commit 8f9622bbb3
7 changed files with 499 additions and 80 deletions

View File

@ -70,6 +70,7 @@
#include "storage/bufmgr.h"
#include "storage/lmgr.h"
#include "storage/lock.h"
#include "storage/predicate.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
@ -1039,6 +1040,14 @@ ExecuteTruncate(TruncateStmt *stmt)
Oid heap_relid;
Oid toast_relid;
/*
* This effectively deletes all rows in the table, and may be done
* in a serializable transaction. In that case we must record a
* rw-conflict in to this transaction from each transaction
* holding a predicate lock on the table.
*/
CheckTableForSerializableConflictIn(rel);
/*
* Need the full transaction-safe pushups.
*
@ -3529,6 +3538,16 @@ ATRewriteTable(AlteredTableInfo *tab, Oid OIDNewHeap, LOCKMODE lockmode)
(errmsg("verifying table \"%s\"",
RelationGetRelationName(oldrel))));
if (newrel)
{
/*
* All predicate locks on the tuples or pages are about to be made
* invalid, because we move tuples around. Promote them to
* relation locks.
*/
TransferPredicateLocksToHeapRelation(oldrel);
}
econtext = GetPerTupleExprContext(estate);
/*