Re: obtaining row locking information

Lists: pgsql-hackers
From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: pgsql-hackers(at)postgresql(dot)org
Subject: obtaining row locking information
Date: 2005-08-07 12:46:08
Message-ID: 20050807.214608.74754910.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Hi,

With a help from Bruce, I wrote a small function which returns row
locking information(see attached file if you are interested). Here is
a sample result:

test=# select * from pgrowlocks('t1');
locked_row | lock_type | locker | multi
------------+-----------+--------+-------
(0,1) | Shared | 1 | t
(0,3) | Exclusive | 575 | f
(2 rows)

I think it will be more usefull if actual xids are shown in the case
"locker" is a multixid. It seems GetMultiXactIdMembers() does the
job. Unfortunately that is a static funtcion, however. Is there any
chance GetMultiXactIdMembers() becomes public funtion?
--
Tatsuo Ishii

Attachment Content-Type Size
unknown_filename text/plain 4.5 KB

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-07 16:57:58
Message-ID: 2523.1123433878@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> With a help from Bruce, I wrote a small function which returns row
> locking information(see attached file if you are interested).

Scanning the whole table seems a bit slow :-(

There is another possibility: in CVS tip, anyone who is actually blocked
on a row lock will be holding a tuple lock that shows exactly what they
are waiting for. For example:

Session 1:

regression=# begin;
BEGIN
regression=# select * from int4_tbl where f1 = 123456 for update;
f1
--------
123456
(1 row)

Session 2:

<< same as above, leaving session 2 blocked >

Session 1:

regression=# select * from pg_locks;
locktype | database | relation | page | tuple | transactionid | classid | objid | objsubid | transaction | pid | mode | granted
---------------+----------+----------+------+-------+---------------+---------+-------+----------+-------------+------+-----------------+---------
transactionid | | | | | 14575 | | | | 14576 | 2501 | ShareLock | f
tuple | 48344 | 48369 | 0 | 2 | | | | | 14576 | 2501 | ExclusiveLock | t
relation | 48344 | 48369 | | | | | | | 14576 | 2501 | AccessShareLock | t
relation | 48344 | 48369 | | | | | | | 14576 | 2501 | RowShareLock | t
transactionid | | | | | 14576 | | | | 14576 | 2501 | ExclusiveLock | t
relation | 48344 | 10339 | | | | | | | 14575 | 2503 | AccessShareLock | t
relation | 48344 | 48369 | | | | | | | 14575 | 2503 | AccessShareLock | t
relation | 48344 | 48369 | | | | | | | 14575 | 2503 | RowShareLock | t
transactionid | | | | | 14575 | | | | 14575 | 2503 | ExclusiveLock | t
(9 rows)

Session 2 (XID 14576) is blocked on session 1 (XID 14575) according to
the first row of this output. The second row shows the exact tuple
that it is after.

This isn't an amazingly user-friendly way of displaying things, of
course, but maybe somebody could make a function that would show it
better using pg_locks as input.

> I think it will be more usefull if actual xids are shown in the case
> "locker" is a multixid. It seems GetMultiXactIdMembers() does the
> job. Unfortunately that is a static funtcion, however. Is there any
> chance GetMultiXactIdMembers() becomes public funtion?

No particular objection here.

regards, tom lane


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: tgl(at)sss(dot)pgh(dot)pa(dot)us
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 07:52:14
Message-ID: 20050808.165214.112628351.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > With a help from Bruce, I wrote a small function which returns row
> > locking information(see attached file if you are interested).
>
> Scanning the whole table seems a bit slow :-(

Yes, but I couldn't find any other way.

> There is another possibility: in CVS tip, anyone who is actually blocked
> on a row lock will be holding a tuple lock that shows exactly what they
> are waiting for. For example:
>
> Session 1:
>
> regression=# begin;
> BEGIN
> regression=# select * from int4_tbl where f1 = 123456 for update;
> f1
> --------
> 123456
> (1 row)
>
> Session 2:
>
> << same as above, leaving session 2 blocked >
>
> Session 1:
>
> regression=# select * from pg_locks;
> locktype | database | relation | page | tuple | transactionid | classid | objid | objsubid | transaction | pid | mode | granted
> ---------------+----------+----------+------+-------+---------------+---------+-------+----------+-------------+------+-----------------+---------
> transactionid | | | | | 14575 | | | | 14576 | 2501 | ShareLock | f
> tuple | 48344 | 48369 | 0 | 2 | | | | | 14576 | 2501 | ExclusiveLock | t
> relation | 48344 | 48369 | | | | | | | 14576 | 2501 | AccessShareLock | t
> relation | 48344 | 48369 | | | | | | | 14576 | 2501 | RowShareLock | t
> transactionid | | | | | 14576 | | | | 14576 | 2501 | ExclusiveLock | t
> relation | 48344 | 10339 | | | | | | | 14575 | 2503 | AccessShareLock | t
> relation | 48344 | 48369 | | | | | | | 14575 | 2503 | AccessShareLock | t
> relation | 48344 | 48369 | | | | | | | 14575 | 2503 | RowShareLock | t
> transactionid | | | | | 14575 | | | | 14575 | 2503 | ExclusiveLock | t
> (9 rows)
>
> Session 2 (XID 14576) is blocked on session 1 (XID 14575) according to
> the first row of this output. The second row shows the exact tuple
> that it is after.
>
> This isn't an amazingly user-friendly way of displaying things, of
> course, but maybe somebody could make a function that would show it
> better using pg_locks as input.

If I understand correctly, it seems the above method does show a
locked row's TID which does not block someone else. That is a little
bit different from what I expcted.

> > I think it will be more usefull if actual xids are shown in the case
> > "locker" is a multixid. It seems GetMultiXactIdMembers() does the
> > job. Unfortunately that is a static funtcion, however. Is there any
> > chance GetMultiXactIdMembers() becomes public funtion?
>
> No particular objection here.
--
Tatsuo Ishii


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 14:26:12
Message-ID: 28118.1123511172@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> If I understand correctly, it seems the above method does show a
> locked row's TID which does not block someone else. That is a little
> bit different from what I expcted.

Well, it *could* be blocking someone else. If there were more than one
waiter for the same tuple, one of them would be holding the tuple lock
(and blocked on the transaction ID of the actual holder of the tuple),
and the other ones would be blocked on the first waiter's tuple lock.
We put this in so that the full lock manager rules would be used to
arbitrate conflicts between shared and exclusive lockers of a tuple.
The tuple lock is being used to manage the grant order and ensure that
a would-be exclusive locker doesn't get "starved out" indefinitely if
there is a continuous chain of shared-lock requests. See the notes in
heap_lock_tuple().

regards, tom lane


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: tgl(at)sss(dot)pgh(dot)pa(dot)us
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 14:36:57
Message-ID: 20050808.233657.59648857.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > If I understand correctly, it seems the above method does show a
> > locked row's TID which does not block someone else. That is a little
> > bit different from what I expcted.
>
> Well, it *could* be blocking someone else. If there were more than one
> waiter for the same tuple, one of them would be holding the tuple lock
> (and blocked on the transaction ID of the actual holder of the tuple),
> and the other ones would be blocked on the first waiter's tuple lock.
> We put this in so that the full lock manager rules would be used to
> arbitrate conflicts between shared and exclusive lockers of a tuple.
> The tuple lock is being used to manage the grant order and ensure that
> a would-be exclusive locker doesn't get "starved out" indefinitely if
> there is a continuous chain of shared-lock requests. See the notes in
> heap_lock_tuple().
>
> regards, tom lane

Sorry, I meant:

If I understand correctly, it seems the above method does *not* show a
locked row's TID which does not block someone else. That is a little
bit different from what I expcted.
--
Tatsuo Ishii


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
Cc: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 14:43:40
Message-ID: 20050808144340.GB26979@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Mon, Aug 08, 2005 at 10:26:12AM -0400, Tom Lane wrote:
> Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > If I understand correctly, it seems the above method does show a
> > locked row's TID which does not block someone else. That is a little
> > bit different from what I expcted.
>
> Well, it *could* be blocking someone else. If there were more than one
> waiter for the same tuple, one of them would be holding the tuple lock
> (and blocked on the transaction ID of the actual holder of the tuple),
> and the other ones would be blocked on the first waiter's tuple lock.

All in all, Tatsuo is right in that there's no way to know what tuples
are locked without scanning the whole table.

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"Those who use electric razors are infidels destined to burn in hell while
we drink from rivers of beer, download free vids and mingle with naked
well shaved babes." (http://slashdot.org/comments.pl?sid=44793&cid=4647152)


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 14:46:38
Message-ID: 20050808144638.GC26979@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Sun, Aug 07, 2005 at 09:46:08PM +0900, Tatsuo Ishii wrote:

> With a help from Bruce, I wrote a small function which returns row
> locking information(see attached file if you are interested).

A quick note: it's easier to build tuples using heap_form_tuple instead
of BuildTupleFromCStrings.

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"Endurecerse, pero jamás perder la ternura" (E. Guevara)


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
Cc: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-08 15:35:17
Message-ID: 28769.1123515317@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org> writes:
> All in all, Tatsuo is right in that there's no way to know what tuples
> are locked without scanning the whole table.

Sure. I was just questioning how much one needs to know that. It seems
to me that the only time you really care is when you are investigating
a hangup, and then you can get useful info from pg_locks.

regards, tom lane


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-12 03:27:25
Message-ID: 20050812.122725.104030712.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Hi,
>
> With a help from Bruce, I wrote a small function which returns row
> locking information(see attached file if you are interested). Here is
> a sample result:
>
> test=# select * from pgrowlocks('t1');
> locked_row | lock_type | locker | multi
> ------------+-----------+--------+-------
> (0,1) | Shared | 1 | t
> (0,3) | Exclusive | 575 | f
> (2 rows)
>
> I think it will be more usefull if actual xids are shown in the case
> "locker" is a multixid. It seems GetMultiXactIdMembers() does the
> job. Unfortunately that is a static funtcion, however. Is there any
> chance GetMultiXactIdMembers() becomes public funtion?

I enhanced pgrowlocks() to use GetMultiXactIdMembers() so that it
displays each xid belonging to particular multi xid (see attached
source code).

test=# select * from pgrowlocks('t1');
locked_row | lock_type | locker | multi | xids
------------+-----------+--------+-------+-----------
(0,1) | Shared | 3 | t | {646,647}
(1 row)

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?
--
Tatsuo Ishii

Attachment Content-Type Size
unknown_filename text/plain 5.1 KB

From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-12 03:50:41
Message-ID: 20050812035041.GA10532@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

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.

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"El que vive para el futuro es un iluso, y el que vive para el pasado,
un imbécil" (Luis Adler, "Los tripulantes de la noche")


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: alvherre(at)alvh(dot)no-ip(dot)org
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-12 05:08:29
Message-ID: 20050812.140829.59654610.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> 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?
--
Tatsuo Ishii


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-12 12:45:39
Message-ID: 20050812124539.GB12111@alvh.no-ip.org
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

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.

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"Thou shalt not follow the NULL pointer, for chaos and madness await
thee at its end." (2nd Commandment for C programmers)


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: alvherre(at)alvh(dot)no-ip(dot)org
Cc: pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-12 14:10:11
Message-ID: 20050812.231011.78703789.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> 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

Attachment Content-Type Size
unknown_filename text/plain 5.3 KB

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-13 02:36:49
Message-ID: 200508130236.j7D2anN01905@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: 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(at)postgresql(dot)org so that your
> message can get through to the mailing list cleanly

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


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: pgman(at)candle(dot)pha(dot)pa(dot)us
Cc: alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-15 14:19:31
Message-ID: 20050815.231931.112624814.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Should this functionality be moved into the backend? When?

Since feature freeze for 8.1 has been already made, I think this
should be into 8.2 or later if necessary.

BTW, I have modified pgrowlocks so that it shows pids:

test=# select * from pgrowlocks('t1');
locked_row | lock_type | locker | multi | xids | pids
------------+-----------+--------+-------+-----------+-------------
(0,1) | Shared | 13 | t | {751,754} | {2259,2261}
(0,4) | Exclusive | 747 | f | {747} | {2255}
(2 rows)

To accomplish this I need to add following function into
storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
that it accepts xid as an argument. Any objection?
--
Tatsuo Ishii

/*
* BackendXidGetProc -- get a backend's PGPROC given its XID
*
* Returns NULL if not found. Note that it is up to the caller to be
* sure that the question remains meaningful for long enough for the
* answer to be used ...
*/
PGPROC *
BackendXidGetProc(TransactionId xid)
{
PGPROC *result = NULL;
ProcArrayStruct *arrayP = procArray;
int index;

if (xid == 0) /* never match dummy PGPROCs */
return NULL;

LWLockAcquire(ProcArrayLock, LW_SHARED);

for (index = 0; index < arrayP->numProcs; index++)
{
PGPROC *proc = arrayP->procs[index];

if (proc->xid == xid)
{
result = proc;
break;
}
}

LWLockRelease(ProcArrayLock);

return result;
}

> ---------------------------------------------------------------------------
>
> 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(at)postgresql(dot)org so that your
> > message can get through to the mailing list cleanly
>
> --
> Bruce Momjian | http://candle.pha.pa.us
> pgman(at)candle(dot)pha(dot)pa(dot)us | (610) 359-1001
> + If your life is a hard drive, | 13 Roberts Road
> + Christ can be your backup. | Newtown Square, Pennsylvania 19073
>


From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: pgman(at)candle(dot)pha(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-15 14:57:13
Message-ID: 26400.1124117833@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> To accomplish this I need to add following function into
> storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> that it accepts xid as an argument. Any objection?

> if (xid == 0) /* never match dummy PGPROCs */
> return NULL;

I think this test should be against InvalidTransactionId, not "0", and
the comment is wrong (you are suppressing matches against idle PGPROCs).

Also note the comment at the top of the function: once you release
ProcArrayLock you have no guarantee that the result means anything at
all; and unlike ProcSendSignal, you have no reason to think that the
target backend can't quit before you get another cycle. It might be
better to return the pid directly rather than assuming it'll still be
meaningful to indirect through a returned pointer.

Also, what are you going to do about prepared transactions? They can
hold locks but they don't have PIDs. On the whole, I'm not sure this
is a good idea at all, because of that.

regards, tom lane


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: tgl(at)sss(dot)pgh(dot)pa(dot)us
Cc: pgman(at)candle(dot)pha(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-17 12:43:19
Message-ID: 20050817.214319.41632032.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > To accomplish this I need to add following function into
> > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > that it accepts xid as an argument. Any objection?
>
> > if (xid == 0) /* never match dummy PGPROCs */
> > return NULL;
>
> I think this test should be against InvalidTransactionId, not "0", and
> the comment is wrong (you are suppressing matches against idle PGPROCs).
>
> Also note the comment at the top of the function: once you release
> ProcArrayLock you have no guarantee that the result means anything at
> all; and unlike ProcSendSignal, you have no reason to think that the
> target backend can't quit before you get another cycle. It might be
> better to return the pid directly rather than assuming it'll still be
> meaningful to indirect through a returned pointer.

Agreed.

> Also, what are you going to do about prepared transactions? They can
> hold locks but they don't have PIDs. On the whole, I'm not sure this
> is a good idea at all, because of that.

For prepared transactions, just showing "0" pids are enough, I
think. Assuming that in practice most transactions are not prepared
ones, I think the function is not perfect, but is usefull enough for
most DBAs.
--
Tatsuo Ishii


From: Alvaro Herrera <alvherre(at)alvh(dot)no-ip(dot)org>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: tgl(at)sss(dot)pgh(dot)pa(dot)us, pgman(at)candle(dot)pha(dot)pa(dot)us, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-19 14:42:40
Message-ID: 20050819144240.GC12685@surnet.cl
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

On Fri, Aug 19, 2005 at 09:19:24PM +0900, Tatsuo Ishii wrote:
> > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > To accomplish this I need to add following function into
> > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > that it accepts xid as an argument. Any objection?

I don't think it is critical for it to return valid answers for
subtransactions, but maybe you should add a note in the commentary about
it:

> /*
> * BackendXidGetPid -- get a backend's pid given its XID
> *
> * Returns 0 if not found or it's a prepared transaction. Note that
> * it is up to the caller to be sure that the question remains
> * meaningful for long enough for the answer to be used ...
*
* Only main transaction Ids are considered. This function is mainly
* useful for determining what backend owns a lock.
> */
> int
> BackendXidGetPid(TransactionId xid)
> {

--
Alvaro Herrera (<alvherre[a]alvh.no-ip.org>)
"The problem with the facetime model is not just that it's demoralizing, but
that the people pretending to work interrupt the ones actually working."
(Paul Graham)


From: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
To: alvherre(at)alvh(dot)no-ip(dot)org
Cc: tgl(at)sss(dot)pgh(dot)pa(dot)us, pgman(at)candle(dot)pha(dot)pa(dot)us, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2005-08-20 00:08:54
Message-ID: 20050820.090854.39154716.t-ishii@sra.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> On Fri, Aug 19, 2005 at 09:19:24PM +0900, Tatsuo Ishii wrote:
> > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > To accomplish this I need to add following function into
> > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > that it accepts xid as an argument. Any objection?
>
> I don't think it is critical for it to return valid answers for
> subtransactions, but maybe you should add a note in the commentary about
> it:
>
> > /*
> > * BackendXidGetPid -- get a backend's pid given its XID
> > *
> > * Returns 0 if not found or it's a prepared transaction. Note that
> > * it is up to the caller to be sure that the question remains
> > * meaningful for long enough for the answer to be used ...
> *
> * Only main transaction Ids are considered. This function is mainly
> * useful for determining what backend owns a lock.
> > */
> > int
> > BackendXidGetPid(TransactionId xid)
> > {

Good point. I will add your comments.
--
Tatsuo Ishii


From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp>
Cc: tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-03-21 03:28:21
Message-ID: 200603210328.k2L3SLE15531@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers


Tatsuo, have you developed a new version of this for 8.2?

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

Tatsuo Ishii wrote:
> > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > To accomplish this I need to add following function into
> > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > that it accepts xid as an argument. Any objection?
> >
> > > if (xid == 0) /* never match dummy PGPROCs */
> > > return NULL;
> >
> > I think this test should be against InvalidTransactionId, not "0", and
> > the comment is wrong (you are suppressing matches against idle PGPROCs).
> >
> > Also note the comment at the top of the function: once you release
> > ProcArrayLock you have no guarantee that the result means anything at
> > all; and unlike ProcSendSignal, you have no reason to think that the
> > target backend can't quit before you get another cycle. It might be
> > better to return the pid directly rather than assuming it'll still be
> > meaningful to indirect through a returned pointer.
>
> Agreed.
>
> > Also, what are you going to do about prepared transactions? They can
> > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > is a good idea at all, because of that.
>
> For prepared transactions, just showing "0" pids are enough, I
> think. Assuming that in practice most transactions are not prepared
> ones, I think the function is not perfect, but is usefull enough for
> most DBAs.
> --
> Tatsuo Ishii
>

--
Bruce Momjian http://candle.pha.pa.us
SRA OSS, Inc. http://www.sraoss.com

+ If your life is a hard drive, Christ can be your backup. +


From: Tatsuo Ishii <ishii(at)sraoss(dot)co(dot)jp>
To: pgman(at)candle(dot)pha(dot)pa(dot)us
Cc: t-ishii(at)sra(dot)co(dot)jp, tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-03-21 11:24:02
Message-ID: 20060321.202402.23031211.t-ishii@sraoss.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

I have attached pgrowlocks tested under current.
--
Tatsuo Ishii
SRA OSS, Inc. Japan

> Tatsuo, have you developed a new version of this for 8.2?
>
> ---------------------------------------------------------------------------
>
> Tatsuo Ishii wrote:
> > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > To accomplish this I need to add following function into
> > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > that it accepts xid as an argument. Any objection?
> > >
> > > > if (xid == 0) /* never match dummy PGPROCs */
> > > > return NULL;
> > >
> > > I think this test should be against InvalidTransactionId, not "0", and
> > > the comment is wrong (you are suppressing matches against idle PGPROCs).
> > >
> > > Also note the comment at the top of the function: once you release
> > > ProcArrayLock you have no guarantee that the result means anything at
> > > all; and unlike ProcSendSignal, you have no reason to think that the
> > > target backend can't quit before you get another cycle. It might be
> > > better to return the pid directly rather than assuming it'll still be
> > > meaningful to indirect through a returned pointer.
> >
> > Agreed.
> >
> > > Also, what are you going to do about prepared transactions? They can
> > > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > > is a good idea at all, because of that.
> >
> > For prepared transactions, just showing "0" pids are enough, I
> > think. Assuming that in practice most transactions are not prepared
> > ones, I think the function is not perfect, but is usefull enough for
> > most DBAs.
> > --
> > Tatsuo Ishii
> >
>
> --
> Bruce Momjian http://candle.pha.pa.us
> SRA OSS, Inc. http://www.sraoss.com
>
> + If your life is a hard drive, Christ can be your backup. +
>

Attachment Content-Type Size
pgrowlocks.tar.gz application/octet-stream 5.5 KB

From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tatsuo Ishii <ishii(at)sraoss(dot)co(dot)jp>
Cc: t-ishii(at)sra(dot)co(dot)jp, tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-04-22 15:11:33
Message-ID: 200604221511.k3MFBXw08772@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers


Tatsuo, are you planning to add this to CVS HEAD?

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

Tatsuo Ishii wrote:
> I have attached pgrowlocks tested under current.
> --
> Tatsuo Ishii
> SRA OSS, Inc. Japan
>
> > Tatsuo, have you developed a new version of this for 8.2?
> >
> > ---------------------------------------------------------------------------
> >
> > Tatsuo Ishii wrote:
> > > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > > To accomplish this I need to add following function into
> > > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > > that it accepts xid as an argument. Any objection?
> > > >
> > > > > if (xid == 0) /* never match dummy PGPROCs */
> > > > > return NULL;
> > > >
> > > > I think this test should be against InvalidTransactionId, not "0", and
> > > > the comment is wrong (you are suppressing matches against idle PGPROCs).
> > > >
> > > > Also note the comment at the top of the function: once you release
> > > > ProcArrayLock you have no guarantee that the result means anything at
> > > > all; and unlike ProcSendSignal, you have no reason to think that the
> > > > target backend can't quit before you get another cycle. It might be
> > > > better to return the pid directly rather than assuming it'll still be
> > > > meaningful to indirect through a returned pointer.
> > >
> > > Agreed.
> > >
> > > > Also, what are you going to do about prepared transactions? They can
> > > > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > > > is a good idea at all, because of that.
> > >
> > > For prepared transactions, just showing "0" pids are enough, I
> > > think. Assuming that in practice most transactions are not prepared
> > > ones, I think the function is not perfect, but is usefull enough for
> > > most DBAs.
> > > --
> > > Tatsuo Ishii
> > >
> >
> > --
> > Bruce Momjian http://candle.pha.pa.us
> > SRA OSS, Inc. http://www.sraoss.com
> >
> > + If your life is a hard drive, Christ can be your backup. +
> >

[ Attachment, skipping... ]

--
Bruce Momjian http://candle.pha.pa.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +


From: Tatsuo Ishii <ishii(at)sraoss(dot)co(dot)jp>
To: pgman(at)candle(dot)pha(dot)pa(dot)us
Cc: ishii(at)sraoss(dot)co(dot)jp, t-ishii(at)sra(dot)co(dot)jp, tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-04-22 23:24:47
Message-ID: 20060423.082447.118629529.t-ishii@sraoss.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Tatsuo, are you planning to add this to CVS HEAD?

Yes, I would like to add if there's no objection.
--
Tatsuo Ishii
SRA OSS, Inc. Japan

> ---------------------------------------------------------------------------
>
> Tatsuo Ishii wrote:
> > I have attached pgrowlocks tested under current.
> > --
> > Tatsuo Ishii
> > SRA OSS, Inc. Japan
> >
> > > Tatsuo, have you developed a new version of this for 8.2?
> > >
> > > ---------------------------------------------------------------------------
> > >
> > > Tatsuo Ishii wrote:
> > > > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > > > To accomplish this I need to add following function into
> > > > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > > > that it accepts xid as an argument. Any objection?
> > > > >
> > > > > > if (xid == 0) /* never match dummy PGPROCs */
> > > > > > return NULL;
> > > > >
> > > > > I think this test should be against InvalidTransactionId, not "0", and
> > > > > the comment is wrong (you are suppressing matches against idle PGPROCs).
> > > > >
> > > > > Also note the comment at the top of the function: once you release
> > > > > ProcArrayLock you have no guarantee that the result means anything at
> > > > > all; and unlike ProcSendSignal, you have no reason to think that the
> > > > > target backend can't quit before you get another cycle. It might be
> > > > > better to return the pid directly rather than assuming it'll still be
> > > > > meaningful to indirect through a returned pointer.
> > > >
> > > > Agreed.
> > > >
> > > > > Also, what are you going to do about prepared transactions? They can
> > > > > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > > > > is a good idea at all, because of that.
> > > >
> > > > For prepared transactions, just showing "0" pids are enough, I
> > > > think. Assuming that in practice most transactions are not prepared
> > > > ones, I think the function is not perfect, but is usefull enough for
> > > > most DBAs.
> > > > --
> > > > Tatsuo Ishii
> > > >
> > >
> > > --
> > > Bruce Momjian http://candle.pha.pa.us
> > > SRA OSS, Inc. http://www.sraoss.com
> > >
> > > + If your life is a hard drive, Christ can be your backup. +
> > >
>
> [ Attachment, skipping... ]
>
> --
> Bruce Momjian http://candle.pha.pa.us
> EnterpriseDB http://www.enterprisedb.com
>
> + If your life is a hard drive, Christ can be your backup. +
>


From: Bruce Momjian <pgman(at)candle(dot)pha(dot)pa(dot)us>
To: Tatsuo Ishii <ishii(at)sraoss(dot)co(dot)jp>
Cc: t-ishii(at)sra(dot)co(dot)jp, tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-04-23 00:21:25
Message-ID: 200604230021.k3N0LPU22142@candle.pha.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Tatsuo Ishii wrote:
> > Tatsuo, are you planning to add this to CVS HEAD?
>
> Yes, I would like to add if there's no objection.

I have heard no comment, and it looks useful, so please add it at your
convenience.

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

> --
> Tatsuo Ishii
> SRA OSS, Inc. Japan
>
> > ---------------------------------------------------------------------------
> >
> > Tatsuo Ishii wrote:
> > > I have attached pgrowlocks tested under current.
> > > --
> > > Tatsuo Ishii
> > > SRA OSS, Inc. Japan
> > >
> > > > Tatsuo, have you developed a new version of this for 8.2?
> > > >
> > > > ---------------------------------------------------------------------------
> > > >
> > > > Tatsuo Ishii wrote:
> > > > > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > > > > To accomplish this I need to add following function into
> > > > > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > > > > that it accepts xid as an argument. Any objection?
> > > > > >
> > > > > > > if (xid == 0) /* never match dummy PGPROCs */
> > > > > > > return NULL;
> > > > > >
> > > > > > I think this test should be against InvalidTransactionId, not "0", and
> > > > > > the comment is wrong (you are suppressing matches against idle PGPROCs).
> > > > > >
> > > > > > Also note the comment at the top of the function: once you release
> > > > > > ProcArrayLock you have no guarantee that the result means anything at
> > > > > > all; and unlike ProcSendSignal, you have no reason to think that the
> > > > > > target backend can't quit before you get another cycle. It might be
> > > > > > better to return the pid directly rather than assuming it'll still be
> > > > > > meaningful to indirect through a returned pointer.
> > > > >
> > > > > Agreed.
> > > > >
> > > > > > Also, what are you going to do about prepared transactions? They can
> > > > > > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > > > > > is a good idea at all, because of that.
> > > > >
> > > > > For prepared transactions, just showing "0" pids are enough, I
> > > > > think. Assuming that in practice most transactions are not prepared
> > > > > ones, I think the function is not perfect, but is usefull enough for
> > > > > most DBAs.
> > > > > --
> > > > > Tatsuo Ishii
> > > > >
> > > >
> > > > --
> > > > Bruce Momjian http://candle.pha.pa.us
> > > > SRA OSS, Inc. http://www.sraoss.com
> > > >
> > > > + If your life is a hard drive, Christ can be your backup. +
> > > >
> >
> > [ Attachment, skipping... ]
> >
> > --
> > Bruce Momjian http://candle.pha.pa.us
> > EnterpriseDB http://www.enterprisedb.com
> >
> > + If your life is a hard drive, Christ can be your backup. +
> >
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: Don't 'kill -9' the postmaster
>

--
Bruce Momjian http://candle.pha.pa.us
EnterpriseDB http://www.enterprisedb.com

+ If your life is a hard drive, Christ can be your backup. +


From: Tatsuo Ishii <ishii(at)sraoss(dot)co(dot)jp>
To: pgman(at)candle(dot)pha(dot)pa(dot)us
Cc: ishii(at)sraoss(dot)co(dot)jp, t-ishii(at)sra(dot)co(dot)jp, tgl(at)sss(dot)pgh(dot)pa(dot)us, alvherre(at)alvh(dot)no-ip(dot)org, pgsql-hackers(at)postgresql(dot)org
Subject: Re: obtaining row locking information
Date: 2006-04-23 01:13:31
Message-ID: 20060423.101331.16517493.t-ishii@sraoss.co.jp
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

> Tatsuo Ishii wrote:
> > > Tatsuo, are you planning to add this to CVS HEAD?
> >
> > Yes, I would like to add if there's no objection.
>
> I have heard no comment, and it looks useful, so please add it at your
> convenience.

Ok, done.
--
Tatsuo Ishii
SRA OSS, Inc. Japan

> ---------------------------------------------------------------------------
>
>
> > --
> > Tatsuo Ishii
> > SRA OSS, Inc. Japan
> >
> > > ---------------------------------------------------------------------------
> > >
> > > Tatsuo Ishii wrote:
> > > > I have attached pgrowlocks tested under current.
> > > > --
> > > > Tatsuo Ishii
> > > > SRA OSS, Inc. Japan
> > > >
> > > > > Tatsuo, have you developed a new version of this for 8.2?
> > > > >
> > > > > ---------------------------------------------------------------------------
> > > > >
> > > > > Tatsuo Ishii wrote:
> > > > > > > Tatsuo Ishii <t-ishii(at)sra(dot)co(dot)jp> writes:
> > > > > > > > To accomplish this I need to add following function into
> > > > > > > > storage/ipc/procarray.c. This is similar to BackendPidGetProc() except
> > > > > > > > that it accepts xid as an argument. Any objection?
> > > > > > >
> > > > > > > > if (xid == 0) /* never match dummy PGPROCs */
> > > > > > > > return NULL;
> > > > > > >
> > > > > > > I think this test should be against InvalidTransactionId, not "0", and
> > > > > > > the comment is wrong (you are suppressing matches against idle PGPROCs).
> > > > > > >
> > > > > > > Also note the comment at the top of the function: once you release
> > > > > > > ProcArrayLock you have no guarantee that the result means anything at
> > > > > > > all; and unlike ProcSendSignal, you have no reason to think that the
> > > > > > > target backend can't quit before you get another cycle. It might be
> > > > > > > better to return the pid directly rather than assuming it'll still be
> > > > > > > meaningful to indirect through a returned pointer.
> > > > > >
> > > > > > Agreed.
> > > > > >
> > > > > > > Also, what are you going to do about prepared transactions? They can
> > > > > > > hold locks but they don't have PIDs. On the whole, I'm not sure this
> > > > > > > is a good idea at all, because of that.
> > > > > >
> > > > > > For prepared transactions, just showing "0" pids are enough, I
> > > > > > think. Assuming that in practice most transactions are not prepared
> > > > > > ones, I think the function is not perfect, but is usefull enough for
> > > > > > most DBAs.
> > > > > > --
> > > > > > Tatsuo Ishii
> > > > > >
> > > > >
> > > > > --
> > > > > Bruce Momjian http://candle.pha.pa.us
> > > > > SRA OSS, Inc. http://www.sraoss.com
> > > > >
> > > > > + If your life is a hard drive, Christ can be your backup. +
> > > > >
> > >
> > > [ Attachment, skipping... ]
> > >
> > > --
> > > Bruce Momjian http://candle.pha.pa.us
> > > EnterpriseDB http://www.enterprisedb.com
> > >
> > > + If your life is a hard drive, Christ can be your backup. +
> > >
> >
> > ---------------------------(end of broadcast)---------------------------
> > TIP 2: Don't 'kill -9' the postmaster
> >
>
> --
> Bruce Momjian http://candle.pha.pa.us
> EnterpriseDB http://www.enterprisedb.com
>
> + If your life is a hard drive, Christ can be your backup. +
>
> ---------------------------(end of broadcast)---------------------------
> TIP 5: don't forget to increase your free space map settings
>