Re: Temporary tables prevent autovacuum, leading to XID wraparound
Michael Paquier <michael@paquier.xyz>
From: Michael Paquier <michael@paquier.xyz>
To: Kyotaro HORIGUCHI <horiguchi.kyotaro@lab.ntt.co.jp>
Cc: tsunakawa.takay@jp.fujitsu.com, tgl@sss.pgh.pa.us, robertmhaas@gmail.com, pgsql-hackers@postgresql.org
Date: 2018-07-27T06:28:40Z
Lists: pgsql-hackers
Attachments
- reset_temp_schema_v3.patch (text/x-diff) patch v3
On Thu, Jul 26, 2018 at 07:05:11PM +0900, Kyotaro HORIGUCHI wrote: > At Wed, 18 Jul 2018 07:34:10 +0000, "Tsunakawa, Takayuki" <tsunakawa.takay@jp.fujitsu.com> wrote in <0A3221C70F24FB45833433255569204D1FA538FD@G01JPEXMBYT05> >> From: Michael Paquier [mailto:michael@paquier.xyz] >>> + /* Does the backend own the temp schema? */ >>> + if (proc->tempNamespaceId != namespaceID) >>> + return false; >>> I have a very hard time believing that this is safe lock-less, and a spin >>> lock would be enough it seems. >> >> The lwlock in BackendIdGetProc() flushes the CPU cache so that >> proc->tempNamespaceId reflects the latest value. Or, do you mean >> another spinlock elsewhere? > > It seems to be allowed that the series of checks on *proc results > in false-positive, which is the safer side for the usage, even it > is not atomically updated. Actually ->databaseId is written > without taking a lock. Well, from postinit.c there are a couple of assumptions in this case, so it is neither white nor black: /* * Now we can mark our PGPROC entry with the database ID. * * We assume this is an atomic store so no lock is needed; though actually * things would work fine even if it weren't atomic. Anyone searching the * ProcArray for this database's ID should hold the database lock, so they * would not be executing concurrently with this store. A process looking * for another database's ID could in theory see a chance match if it read * a partially-updated databaseId value; but as long as all such searches * wait and retry, as in CountOtherDBBackends(), they will certainly see * the correct value on their next try. */ MyProc->databaseId = MyDatabaseId; Anyway, I have spent some time on this patch, and the thing is doing a rather bad job about why it is fine to assume that the update can happen lock-less, and the central part of it seems to be that autovacuum cannot see the temporary schema created, and any objects on it when it scans pg_class until it gets committed, and the tracking field is updated in PGPROC before the commit. > backend_uses_temp_namespace is taking two parameters but the > first one is always derived from the second. backendID doesn't > seem to be needed outside so just one parameter namespaceID is > needed. Yes, that reduces the number of calls to GetTempNamespaceBackendId. autovacuum.c is a pretty bad place for stuff as namespace.c holds all the logic related to temporary tablespaces, so I renamed the routine to isTempNamespaceInUse and moved it there. The patch I have now is attached. I have not been able to test it much, particularly with orphaned temp tables and autovacuum, which is something I'll try to look at this week end or perhaps at the beginning of next week, heading toward a commit if I am fine enough with it. Please feel free to look at it for the time being. Thanks, -- Michael
Commits
-
Clarify comment about assignment and reset of temp namespace ID in MyProc
- 9fc9933695af 11.0 landed
- 1339fcc89617 12.0 landed
-
Make autovacuum more aggressive to remove orphaned temp tables
- 943576bddcb5 11.0 landed
- 246a6c8f7b23 12.0 landed
-
Don't count background workers against a user's connection limit.
- 13752743bf70 9.6.2 cited