Re: obtaining row locking information

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: obtaining row locking information
Дата
Msg-id 200508130236.j7D2anN01905@candle.pha.pa.us
обсуждение исходный текст
Ответ на Re: obtaining row locking information  (Tatsuo Ishii <t-ishii@sra.co.jp>)
Ответы Re: obtaining row locking information  (Tatsuo Ishii <t-ishii@sra.co.jp>)
Список pgsql-hackers
Should this functionality be moved into the backend?  When?

---------------------------------------------------------------------------

Tatsuo Ishii wrote:
> > On Fri, Aug 12, 2005 at 02:08:29PM +0900, Tatsuo Ishii wrote:
> > > > On Fri, Aug 12, 2005 at 12:27:25PM +0900, Tatsuo Ishii wrote:
> > > > 
> > > > > However even one of transactions, for example 647 commits, still it
> > > > > shows as if 647 is a member of muitixid 3.
> > > > > 
> > > > > test=# select * from pgrowlocks('t1');
> > > > >  locked_row | lock_type | locker | multi |   xids    
> > > > > ------------+-----------+--------+-------+-----------
> > > > >       (0,1) | Shared    |      3 | t     | {646,647}
> > > > > (1 row)
> > > > > 
> > > > > Am I missing something?
> > > > 
> > > > By design, a MultiXactId does not change its membership, that is, no
> > > > members are added nor deleted.  When this has to happen (for example a
> > > > row is locked by another backend), a new MultiXactId is generated.  The
> > > > caller is expected to check whether the member transactions are still
> > > > running.
> > > 
> > > But it seems when members are deleted, new multixid is not
> > > generated. i.e. I see "locker" column does not change. Is this an
> > > expected behavior?
> > 
> > Yes.  Members are never deleted.  This is for two reasons: first, the
> > transaction could theoretically hold millions of MultiXactId, and we
> > can't expect it to remember them all; so we don't have a way to find out
> > which ones it should clean up when it finishes (a process which would be
> > slow and cumbersome anyway).  Second, because the implementation does
> > not really allow for shrinking (nor enlarging) an array.  Once created,
> > the array is immutable.
> > 
> > If you locked a tuple with transactions B and C; then transaction B
> > committed; then transaction D locked the tuple again, you would see a
> > new MultiXactId comprising transactions C and D.
> 
> Ok, here is the new version of the function which now checks if the
> transactions are still running.
> 
> BTW, I think it would be helpfull if the function returns the process
> id which runs the transaction. I couldn't find any existing function
> which converts an xid to a process id so far, and think inventing
> someting like BackendPidGetProc(int pid) would be the way I should
> go. Any suggestion?
> --
> Tatsuo Ishii

> /*
>  * $PostgreSQL$
>  *
>  * Copyright (c) 2005    Tatsuo Ishii
>  *
>  * Permission to use, copy, modify, and distribute this software and
>  * its documentation for any purpose, without fee, and without a
>  * written agreement is hereby granted, provided that the above
>  * copyright notice and this paragraph and the following two
>  * paragraphs appear in all copies.
>  *
>  * IN NO EVENT SHALL THE AUTHOR BE LIABLE TO ANY PARTY FOR DIRECT,
>  * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
>  * LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
>  * DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED
>  * OF THE POSSIBILITY OF SUCH DAMAGE.
>  *
>  * THE AUTHOR SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
>  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>  * A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS
>  * IS" BASIS, AND THE AUTHOR HAS NO OBLIGATIONS TO PROVIDE MAINTENANCE,
>  * SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
>  */
> 
> #include "postgres.h"
> 
> #include "funcapi.h"
> #include "access/heapam.h"
> #include "access/multixact.h"
> #include "access/transam.h"
> #include "catalog/namespace.h"
> #include "catalog/pg_type.h"
> #include "storage/procarray.h"
> #include "utils/builtins.h"
> 
> 
> PG_FUNCTION_INFO_V1(pgrowlocks);
> 
> extern Datum pgrowlocks(PG_FUNCTION_ARGS);
> 
> /* ----------
>  * pgrowlocks:
>  * returns tids of rows being locked
>  *
>  * C FUNCTION definition
>  * pgrowlocks(text) returns set of pgrowlocks_type
>  * see pgrowlocks.sql for pgrowlocks_type
>  * ----------
>  */
> 
> #define DUMMY_TUPLE "public.pgrowlocks_type"
> #define NCHARS 32
> 
> /*
>  * define this if makeRangeVarFromNameList() has two arguments. As far
>  * as I know, this only happens in 8.0.x.
>  */
> #undef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS
> 
> typedef struct {
>     HeapScanDesc scan;
>     int ncolumns;
> } MyData;
> 
> Datum
> pgrowlocks(PG_FUNCTION_ARGS)
> {
>     FuncCallContext *funcctx;
>     HeapScanDesc scan;
>     HeapTuple    tuple;
>     TupleDesc    tupdesc;
>     AttInMetadata *attinmeta;
>     Datum        result;
>     MyData *mydata;
>     Relation    rel;
> 
>     if (SRF_IS_FIRSTCALL())
>     {
>         text       *relname;
>         RangeVar   *relrv;
>         MemoryContext oldcontext;
> 
>         funcctx = SRF_FIRSTCALL_INIT();
>         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
> 
>         tupdesc = RelationNameGetTupleDesc(DUMMY_TUPLE);
>         attinmeta = TupleDescGetAttInMetadata(tupdesc);
>         funcctx->attinmeta = attinmeta;
> 
>         relname = PG_GETARG_TEXT_P(0);
> #ifdef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS
>         relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname,
   "pgrowlocks"));
 
> 
> #else
>         relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
> #endif
>         rel = heap_openrv(relrv, AccessShareLock);
>         scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
>         mydata = palloc(sizeof(*mydata));
>         mydata->scan = scan;
>         mydata->ncolumns = tupdesc->natts;
>         funcctx->user_fctx = mydata;
> 
>         MemoryContextSwitchTo(oldcontext);
>     }
> 
>     funcctx = SRF_PERCALL_SETUP();
>     attinmeta = funcctx->attinmeta;
>     mydata = (MyData *)funcctx->user_fctx;
>     scan = mydata->scan;
> 
>     /* scan the relation */
>     while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
>     {
>         /* must hold a buffer lock to call HeapTupleSatisfiesUpdate */
>         LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
> 
>         if (HeapTupleSatisfiesUpdate(tuple->t_data, GetCurrentCommandId(), scan->rs_cbuf)
>             == HeapTupleBeingUpdated)
>         {
> 
>             char **values;
>             int i;
> 
>             values = (char **) palloc(mydata->ncolumns * sizeof(char *));
> 
>             i = 0;
>             values[i++] = (char *)DirectFunctionCall1(tidout, PointerGetDatum(&tuple->t_self));
> 
> #ifdef HEAP_XMAX_SHARED_LOCK
>             if (tuple->t_data->t_infomask & HEAP_XMAX_SHARED_LOCK)
>                 values[i++] = pstrdup("Shared");
>             else
>                 values[i++] = pstrdup("Exclusive");
> #else
>             values[i++] = pstrdup("Exclusive");
> #endif
>             values[i] = palloc(NCHARS*sizeof(char));
>             snprintf(values[i++], NCHARS, "%d", HeapTupleHeaderGetXmax(tuple->t_data));
> #ifdef HEAP_XMAX_SHARED_LOCK
>             if (tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI)
>             {
>                 TransactionId *xids;
>                 int nxids;
>                 int j;
>                 int isValidXid = 0;        /* any valid xid ever exists? */
> 
>                 values[i++] = pstrdup("true");
>                 nxids = GetMultiXactIdMembers(HeapTupleHeaderGetXmax(tuple->t_data), &xids);
>                 if (nxids == -1)
>                 {
>                     elog(ERROR, "GetMultiXactIdMembers returns error");
>                 }
> 
>                 values[i] = palloc(NCHARS*nxids);
>                 strcpy(values[i], "{");
> 
>                 for (j=0;j<nxids;j++)
>                 {
>                     char buf[NCHARS];
> 
>                     if (TransactionIdIsInProgress(xids[j]))
>                     {
>                         if (isValidXid)
>                         {
>                             strcat(values[i], ",");
>                         }
>                         snprintf(buf, NCHARS, "%d", xids[j]);
>                         strcat(values[i], buf);
>                         isValidXid = 1;
>                     }
>                 }
> 
>                 strcat(values[i], "}");
>                 i++;
>             }
>             else
>             {
>                 values[i++] = pstrdup("false");
>                 values[i++] = pstrdup("{}");
>             }
> #else
>             values[i++] = pstrdup("false");
>             values[i++] = pstrdup("{}");
> #endif
> 
>             LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
> 
>             /* build a tuple */
>             tuple = BuildTupleFromCStrings(attinmeta, values);
> 
>             /* make the tuple into a datum */
>             result = HeapTupleGetDatum(tuple);
> 
>             /* Clean up */
>             for (i = 0; i < mydata->ncolumns; i++)
>                 pfree(values[i]);
>             pfree(values);
> 
>             SRF_RETURN_NEXT(funcctx, result);
>         }
>         else
>         {
>             LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
>         }
>     }
> 
>     heap_endscan(scan);
>     heap_close(scan->rs_rd, AccessShareLock);
> 
>     SRF_RETURN_DONE(funcctx);
> }

> 
> ---------------------------(end of broadcast)---------------------------
> TIP 1: if posting/reading through Usenet, please send an appropriate
>        subscribe-nomail command to majordomo@postgresql.org so that your
>        message can get through to the mailing list cleanly

--  Bruce Momjian                        |  http://candle.pha.pa.us pgman@candle.pha.pa.us               |  (610)
359-1001+  If your life is a hard drive,     |  13 Roberts Road +  Christ can be your backup.        |  Newtown Square,
Pennsylvania19073
 


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

Предыдущее
От: Bruce Momjian
Дата:
Сообщение: Re: gettime() - a timeofday() alternative
Следующее
От: Bruce Momjian
Дата:
Сообщение: Re: [PATCHES] prevent encoding conversion recursive error