I've been continuing work on modifying the system to let foreign keys coexist concurrently with updates that do not touch the "key" columns. I've made a lot of progress and things seem to be working rather well. However, I just struck an obstacle that seemed problematic: handling the truncation of the MultiXactId space when they are no longer needed.
I hadn't stopped to think much about this, regarding it as a trivial problem to change multixact.c to be just like clog.c. However, when it came to actually doing it, I immediately realized that this cannot work, because they don't share a common numeric space -- the mxact counter can be anywhere, unrelated to the Xid counter. There's no way to figure out the mutixact truncation point from purely Xid data. In search of solutions to this problem, two things came to mind: 1. Track MultiXact offset generation just as we track Xid generation. This means that after vacuum we immediately know where to truncate. 2. Make them share a common numeric space. Both those two solutions come at a very high cost. #1 means that we need some sort of "frozenmxact" column in pg_class and pg_database. So we'd know easily and precisely where to truncate mxact; but we would bloat those catalogs for something that's not as important. (We eat the cost of maintaining relfrozenxid and datfrozenxid because it's necessary for the system to work at all; but in the mxact case, we're talking about something that's merely a concurrency optimization). In the case of #2, we avoid having to add those columns, by having multixact offsets be assigned by GetNewTransactionId; thus, we can easily know where to truncate just by truncating at the same spot that we truncate pg_clog. The problem with this idea is that there would be huge areas of pg_multixact/offset that are completely unused, because they would correspond to the values assigned to Xids themselves. This would lead to bloat of multixact. It would also lead to shortening the useful Xid space, thus leading to shorter times to freeze vacuum. This is, of course, completely unacceptable. So I had to look for something else -- and I think I have it: have multixact itself track its truncation position relative to Xid. Each pg_multixact/offset segment would store ReadNewTransactionId at the time it is created. Whenever vacuum attempts to run pg_clog truncation, it would also pass that Xid to multixact truncation; this would scan existing segments and delete those that come before the one marked with the maximum Xid previous to the pg_clog truncation point. Doing this will require hacking the SLRU truncation logic a bit, so that it's possible to have it scan segments with a callback in some fashion. Thoughts? -- Álvaro Herrera <alvhe...@alvh.no-ip.org> -- Sent via pgsql-hackers mailing list (firstname.lastname@example.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers