DROP TABLE and concurrent modifications - Mailing list pgsql-hackers
| From | Neil Conway |
|---|---|
| Subject | DROP TABLE and concurrent modifications |
| Date | |
| Msg-id | 871xoui0j6.fsf@mailbox.samurai.com Whole thread Raw |
| Responses |
Re: DROP TABLE and concurrent modifications
Re: DROP TABLE and concurrent modifications |
| List | pgsql-hackers |
I can reproduce the following behavior with CVS HEAD.
1. Have a process do INSERTs into a table in a tight loop (I've attached a trivial libpq app that does this)
2. In another session, repeatedly drop and re-create the table that is being modified
You should see a stream of error messages from the INSERT client like:
query failed: ERROR: relation 29118 deleted while still in use
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation 32430 deleted while still in use
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation "test_tbl" does not exist
query failed: ERROR: relation 34206 deleted while still in use
The problem is the variant of the error message. When the error
message variant occurs, the INSERT backend is in the following state:
[ ... ]
#2 0x0824ff48 in RelationClearRelation (relation=0x40c92538, rebuild=1 '\001') at relcache.c:1711
#3 0x0825006e in RelationFlushRelation (relation=0x40c92538) at relcache.c:1775
#4 0x082501b5 in RelationCacheInvalidateEntry (relationId=17145, rnode=0x0) at relcache.c:1842
#5 0x0824d153 in LocalExecuteInvalidationMessage (msg=0xbfffeed0) at inval.c:452
#6 0x081c6af5 in ReceiveSharedInvalidMessages (invalFunction=0x824d043 <LocalExecuteInvalidationMessage>,
resetFunction=0x824d213<InvalidateSystemCaches>) at sinval.c:125
#7 0x0824d3c6 in AcceptInvalidationMessages () at inval.c:611
#8 0x081c8f99 in LockRelation (relation=0x40c92538, lockmode=3) at lmgr.c:143
#9 0x08089232 in relation_open (relationId=17145, lockmode=3) at heapam.c:462
#10 0x080892c9 in relation_openrv (relation=0x83956e0, lockmode=3) at heapam.c:506
#11 0x08089576 in heap_openrv (relation=0x83956e0, lockmode=3) at heapam.c:610
#12 0x080ee857 in setTargetTable (pstate=0x83955ec, relation=0x83956e0, inh=0 '\0', alsoSource=0 '\0', requiredPerms=1)
atparse_clause.c:142
#13 0x080d4390 in transformInsertStmt (pstate=0x83955ec, stmt=0x8395808, extras_before=0xbffff0a0,
extras_after=0xbffff09c)at analyze.c:543
[ ... ]
i.e. it is waiting to acquire a lock on the relation it wants to
INSERT into, but before returning from LockRelation() it receives a
shared-cache invalidation message for the relation the other backend
has just dropped. This causes it to error out in the bowels of
RelationClearRelation():
if (RelationBuildDesc(buildinfo, relation) != relation) { /* Should only get here if relation was deleted
*/ FreeTupleDesc(old_att); if (old_rulescxt) MemoryContextDelete(old_rulescxt);
pfree(relation); elog(ERROR, "relation %u deleted while still in use", buildinfo.i.info_id); }
Assuming my analysis is correct, is this a bug?
AFAICS it should be totally harmless, but at the least it would be
nice to display a more friendly/informative error message. Can anyone
see a way to do this without too much pain?
-Neil
pgsql-hackers by date: