Facing a problem with SPI

Поиск
Список
Период
Сортировка
От Gurjeet Singh
Тема Facing a problem with SPI
Дата
Msg-id 65937bea0612030309n2555f6b4qdacb57b31c1617ba@mail.gmail.com
обсуждение исходный текст
Ответы Re: Facing a problem with SPI  ("Gurjeet Singh" <singh.gurjeet@gmail.com>)
Список pgsql-hackers
<span style="font-family: courier new,monospace;">Hi all,<br /><br />    I am facing a problem with the SPI (spi.c). I
haveimplemented short-lived virtual indexes using SubTransactions. The Index Adviser, when creating virtual indexes,
createsthem inside a SubTransaction, and when it is done with its advisory stuff, it rolls back the SubTransaction.
Thisachieves two objectives: <br /><br />    (1) Easy cleanup of dependencies/changes in the catalog.<br />    (2) The
virtualindexes are not visible to other backends. This eliminates the possibility of other backends (not running in
Advisemode) seeing these indexes, as these don't have any data in them. <br /><br />    So all the index
creation/deletionis done between a pair of BeginInternalSubTransaction() (BIST()) and
RollbackAndReleaseCurrentSubTransaction()(RARCST()). This all works well when we are EXPLAINing query in special advise
mode.<br /><br />    Now, based on this, I wanted to generate advise for every query that comes for planning, be it
frompsql or pl/pgsql or anywhere else. So I made a function call to the index_adviser() from within pg_plan_query()
afterthe planner() call. <br /><br />    The problem I am facing is that that the queries being planned by pl/pgsql,
comeafter a call to SPI_connect() and SPI_Prepare(). SPI_prepare() switches to _SPI_current->execCxt memory context
using_SPI_begin_call(). <br /><br />    Everything goes well until the index_adviser() calls RARCST() to rollback it's
SubTransaction.RARCST() ultimately ends up calling AtEOSubXact_SPI(), which, just before returning, deletes the
executionmemory context of the surrounding SPI (which happens to be pl/pgsql's SPI). This, in effect, frees all the
memoryallocated by pl/pgsql for the prepare stage; and the next time the pl/pgsql's data-structures are referenced, it
causesa crash. The code in question is: <br /><br />void<br />AtEOSubXact_SPI(bool isCommit, SubTransactionId
mySubid)<br/>{<br />    bool        found = false;<br /><br />    while (_SPI_connected >= 0)<br />    {<br
/>       _SPI_connection *connection = &(_SPI_stack[_SPI_connected]); <br /><br />        if
(connection->connectSubid!= mySubid)<br />            break;              /* couldn't be any underneath it either
*/<br/><br />        ......<br />        ......<br />    /*<br />     * If we are aborting a subtransaction and there
isan open SPI context <br />     * surrounding the subxact, clean up to prevent memory leakage.<br />     */<br />   
if(_SPI_current && !isCommit)<br />    {<br />        /* free Executor memory the same as _SPI_end_call would
do*/<br />        MemoryContextResetAndDeleteChildren(_SPI_current->execCxt); <br />        ^^^^^^^^^^^<br />       
/*throw away any partially created tuple-table */<br />        SPI_freetuptable(_SPI_current->tuptable);<br
/>       _SPI_current->tuptable = NULL;<br />    }<br />}<br /><br />    The code is doing what the comments say,
buthow I wish it didn't. This code assumes that the latest BIST() came from a SPI invoking module, which the Index
Adviseris not! <br /><br />    I haven't been able to come up with a proof, but I think this situation can be
simulated/reproducedusing some pl/* language that we support.<br /><br />    pl/pgsql is safe, since it doesn't allow
SAVEPOINT/ROLLBACKTO SAVEPOINT inside it's code blocks; but if some pl/xxx allows SAVEPOINTS, I think it can be
reproducedusing something like: <br /><br />    SAVEPOINT xxx            ( should call BIST() )<br />        SAVEPOINT
yyy       ( should call BIST() )<br />        Rollback (to yyy)    ( should call RARCST() ) will free pl/xxx exec
context<br/>    Rollback (to xxx)        ( should call RARCST() ) <br /><br />    Probably just one pair, instead of
twonested ones, should reproduce it. I tried to reproduce it using pl/pgsql's exception block (there we use BIST() and
RARCST());but couldn't succeed.<br /><br />    I hope I have understood the issue correctly, or have I missed
something?Is there a way to work around this? <br /><br />Best regards,<br clear="all" style="font-family: courier
new,monospace;"/></span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">--</span><br style="font-family: courier new,monospace;" /><span style="font-family: courier
new,monospace;">gurjeet[.singh]@EnterpriseDB.com</span><brstyle="font-family: courier new,monospace;" /><span
style="font-family:courier new,monospace;">singh.gurjeet@{ gmail | hotmail | yahoo }.com </span> 

В списке pgsql-hackers по дате отправления:

Предыдущее
От: "Magnus Hagander"
Дата:
Сообщение: Re: PostgreSQL win32 fragmentation issue
Следующее
От: "Gurjeet Singh"
Дата:
Сообщение: Re: Facing a problem with SPI