Issue with server side statement-level rollback

From: Gilles Darold <gilles(at)darold(dot)net>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Issue with server side statement-level rollback
Date: 2020-11-12 10:40:22
Message-ID: 71eab1a3-8f77-c00f-28ea-7b1a484f71d9@darold.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi,

We're facing some issue in a new extension we use at LzLabs to
emulate server side rollback at statement level in PostgreSQL,
see for full detail https://github.com/lzlabs/pg_statement_rollback/

The problem we are encountering is when PostgreSQL is compiled in debug
mode with --enable-cassert. At line 1327 of src/backend/tcop/pquery.c
the following assert fail:

    /*
     * Clear subsidiary contexts to recover temporary memory.
     */
    Assert(portal->portalContext == CurrentMemoryContext);

    MemoryContextDeleteChildren(portal->portalContext);

This extension, although it is a risky implementation, works extremely
well when used in a fully controlled environment. It avoid the latency
of the extra communication for the RELEASE+SAVEPOINT usually controlled at
client side. The client is only responsible to issue the "ROLLBACK TO
autosavepoint"
when needed.  The extension allow a high performances gain for this feature
that helps customers using Oracle or DB2 to migrate to PostgreSQL.

Actually with the extension the memory context is not CurrentMemoryContext
as expected by the assert.

    (gdb) b pquery.c:1327
    Breakpoint 1 at 0x55792fd7a04d: file pquery.c, line 1327.
    (gdb) c
    Continuing.

    Breakpoint 1, PortalRunMulti (portal=portal(at)entry=0x5579316e3e10,
isTopLevel=isTopLevel(at)entry=true,
        setHoldSnapshot=setHoldSnapshot(at)entry=false,
dest=dest(at)entry=0x557931755ce8, altdest=altdest(at)entry=0x557931755ce8,
        qc=qc(at)entry=0x7ffc4aa1f8a0) at pquery.c:1327
    1327            Assert(portal->portalContext == CurrentMemoryContext);
    (gdb) p portal->sourceText
    $1 = 0x557931679c80 "INSERT INTO savepoint_test SELECT 1;"
    (gdb) p MemoryContextStats(portal->portalContext)
    $2 = void
    (gdb)

The memory context dump output from log:

    PortalContext: 1024 total in 1 blocks; 704 free (1 chunks); 320
used: <unnamed>
    Grand total: 1024 bytes in 1 blocks; 704 free (1 chunks); 320 used

If I naively remove the assert on pquery.c everything works without any
new assert error.

As I said I am aware that this is clearly not a standard PostgreSQL use
but we have no choice. We are emulating DB2 statement-level rollback
behavior and we have chosen to not create a new fork of PostgreSQL and
only work with extensions. As there is no hook or API that could allow a
perfect
server side integration of this feature we have done what is possible to do
in the extension.

So my question is should we allow such use through an extension and in
this case what is the change to PostgreSQL code that could avoid the
assert crash? Or perhaps we have missed something in this extension to
be able to make the assert happy but I don't think so.

Cheers

--
Gilles Darold

Responses

Browse pgsql-hackers by date

  From Date Subject
Next Message Alexey Kondratov 2020-11-12 10:47:34 Re: Misuse of TimestampDifference() in the autoprewarm feature of pg_prewarm
Previous Message Sergei Kornilov 2020-11-12 10:34:46 ​generated columns in MergeAttributesIntoExisting