Thread: userlock changes for 8.1/8.2

userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
Ok,

With 8.0 out the door, I'd like to reopen discussion re: userlock
contrib. module and propose to get it moved into the core database
sources.  This was discussed a bit a few months back but it never made
it officially to the todo list.  I'm not sure what the final consensus
was on the shared locks discussion, but it might be a good idea to
consider user locks at the same time (and vise versa), since they might
invoke related changes to the documentation, etc.  At the very least,
I'd like to know that if properly documented, userlocks stand a chance
of being upgraded to the core project.

First, a little about the current userlock module:
1. It is GPL.  However, the module is nothing more than a couple of
wrappers to the backend functions LockAcquire, LockRelease, etc. and
some documentation.  I'm suggesting to recode the wrappers and redo the
documentation as well in the BSD license.

2. userlocks provide a very powerful and high performance method of row
level locking.   With a little bit of clever coding, they can do other
tricks...

3. The current system view, pg_locks, does not display enough
information about user locks...I'd suggest either expanding the current
view and/or adding a new view, pg_user_locks (along with new function in
lockfuncs.c)

4. Current user locks implementation is missing (at least 2) important
features...1. ability of superuser to kill a lock owned by another user
(corollary: does lockrelease support this?), and 2. the ability to deal
with the full 48 bit lock as a single datum (new system type?).  Would
also be nice to have a lockmode that waits for a lock for a period of
time.

5. Need lots of documentation changes...would like to beef up section
covering lock module, plus better description of runtime setting
'max_locks_per_transation' including a possible rename.

Merlin



Re: userlock changes for 8.1/8.2

From
"Jim C. Nasby"
Date:
Speaking of other tricks and things missing; I'd like to see support for
named locks. If you're using locks for something other than row-level
locking, it's awkward at best to have to come up with an OID to identify
your lock with, and even that doesn't guarantee uniqueness. You're also
out of luck if the table you're doing row level locking on doesn't have
OIDs. You also can't do direct OID locking on more than one table in an
application.

I think two different naming facilities would be of use:
1) A namespace for single locks, where each lock has it's own name.
2) A namespace for a set of locks. Another way to look at this would be
a namespace for group IDs.

I realize that this conflicts with the existing userlock implementation,
so it might be necessary to have a second set of locks to support this.

On Mon, Jan 24, 2005 at 01:31:34PM -0500, Merlin Moncure wrote:
> Ok, 
> 
> With 8.0 out the door, I'd like to reopen discussion re: userlock
> contrib. module and propose to get it moved into the core database
> sources.  This was discussed a bit a few months back but it never made
> it officially to the todo list.  I'm not sure what the final consensus
> was on the shared locks discussion, but it might be a good idea to
> consider user locks at the same time (and vise versa), since they might
> invoke related changes to the documentation, etc.  At the very least,
> I'd like to know that if properly documented, userlocks stand a chance
> of being upgraded to the core project.
> 
> First, a little about the current userlock module:
> 1. It is GPL.  However, the module is nothing more than a couple of
> wrappers to the backend functions LockAcquire, LockRelease, etc. and
> some documentation.  I'm suggesting to recode the wrappers and redo the
> documentation as well in the BSD license.
> 
> 2. userlocks provide a very powerful and high performance method of row
> level locking.   With a little bit of clever coding, they can do other
> tricks...
> 
> 3. The current system view, pg_locks, does not display enough
> information about user locks...I'd suggest either expanding the current
> view and/or adding a new view, pg_user_locks (along with new function in
> lockfuncs.c)
> 
> 4. Current user locks implementation is missing (at least 2) important
> features...1. ability of superuser to kill a lock owned by another user
> (corollary: does lockrelease support this?), and 2. the ability to deal
> with the full 48 bit lock as a single datum (new system type?).  Would
> also be nice to have a lockmode that waits for a lock for a period of
> time.
> 
> 5. Need lots of documentation changes...would like to beef up section
> covering lock module, plus better description of runtime setting
> 'max_locks_per_transation' including a possible rename.
> 
> Merlin
> 
>  
> 
> ---------------------------(end of broadcast)---------------------------
> TIP 9: the planner will ignore your desire to choose an index scan if your
>       joining column's datatypes do not match
> 

-- 
Jim C. Nasby, Database Consultant               decibel@decibel.org 
Give your computer some brain candy! www.distributed.net Team #1828

Windows: "Where do you want to go today?"
Linux: "Where do you want to go tomorrow?"
FreeBSD: "Are you guys coming, or what?"


Re: userlock changes for 8.1/8.2

From
Tom Lane
Date:
"Jim C. Nasby" <decibel@decibel.org> writes:
> Speaking of other tricks and things missing; I'd like to see support for
> named locks.

[ yawn... ]  Create a table with a "name" column, put some rows in it,
lock the rows.
        regards, tom lane


Re: userlock changes for 8.1/8.2

From
"Jim C. Nasby"
Date:
On Mon, Jan 24, 2005 at 10:43:40PM -0500, Tom Lane wrote:
> "Jim C. Nasby" <decibel@decibel.org> writes:
> > Speaking of other tricks and things missing; I'd like to see support for
> > named locks.
> 
> [ yawn... ]  Create a table with a "name" column, put some rows in it,
> lock the rows.

What would guarantee that the OIDs of those rows don't conflict with
some other OIDs in the system?

BTW, this becomes a real issue if you're trying to write code that is
meant to be incorporated into other PostgreSQL applications, which might
also be using user_lock. Having a text-based means to identify locks
greatly reduces the odds of conflicting with a userlock being used by an
existing application.
-- 
Jim C. Nasby, Database Consultant               decibel@decibel.org 
Give your computer some brain candy! www.distributed.net Team #1828

Windows: "Where do you want to go today?"
Linux: "Where do you want to go tomorrow?"
FreeBSD: "Are you guys coming, or what?"


Re: userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
> > [ yawn... ]  Create a table with a "name" column, put some rows in
it,
> > lock the rows.
>
> What would guarantee that the OIDs of those rows don't conflict with
> some other OIDs in the system?
>
> BTW, this becomes a real issue if you're trying to write code that is
> meant to be incorporated into other PostgreSQL applications, which
might
> also be using user_lock. Having a text-based means to identify locks
> greatly reduces the odds of conflicting with a userlock being used by
an
> existing application.

I prefer sequences to OIDs in virtually every aspect, including this
one.  However, it would be nice to have system generated unique tuple
identifier.  There isn't one currently that would fit in the userlock
restriction of 48 bits.  Any identifier derived from system columns
probably would take 96-128 bits (for example ctid/tableoid combo).

IMO, the current behavior is ok, meaning I don't necessarily feel that
there should be a candidate system key to use for them.  However I would
discourage the use of OIDs with them.

Merlin


Re: userlock changes for 8.1/8.2

From
Tom Lane
Date:
"Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> However, it would be nice to have system generated unique tuple
> identifier.  There isn't one currently that would fit in the userlock
> restriction of 48 bits.

Sure there is: the ctid of a row in an agreed-on table works fine.
The reason it's system-wide unique is that user_locks.c forcibly
includes your database OID in the lock tag.

It would be reasonable to allow user control of the lock's relId field
and maybe even dbId field, but that just takes an expansion of the API
for user_locks.c.  There's no need to put overhead on the rest of
Postgres for this.
        regards, tom lane


Re: userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
Tom Lane wrote:
> "Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> > However, it would be nice to have system generated unique tuple
> > identifier.  There isn't one currently that would fit in the
userlock
> > restriction of 48 bits.
>
> Sure there is: the ctid of a row in an agreed-on table works fine.
> The reason it's system-wide unique is that user_locks.c forcibly
> includes your database OID in the lock tag.
>
> It would be reasonable to allow user control of the lock's relId field
> and maybe even dbId field, but that just takes an expansion of the API
> for user_locks.c.  There's no need to put overhead on the rest of
> Postgres for this.

Ok, you answered my next question.  Part of my confusion here is the
comments in front of LockAcquire() which explains how userlocks are
supposed to be mapped to the lock tag.  In the case of userlocks, the
locktag is basically a hash key, right?  so we can recover the other
fields and have enough room to play with to generate a 'real'
identifier, but...

ctid is useless for user locks because an update from a non-cooperating
client will change it unless the locks become non-cooperative, and now
we are talking about classic row level locks...not worth considering
IMO.  IOW, a 'user lock' candidate identifier generated by the database
must be both unique and persistent for the lifetime of the lock.

Without using ctid (and don't want to use oid), there is nothing that
can be pulled from the tuple that persistently identifies it until the
oid is extended to 64 bits or beyond which doesn't seem likely at this
point, so we are back to the classic approach of using an application
managed sequence.


So the only changes to the current sources in the core project outside
of documentation are:

1. update comments to LockAcuire() in lock.c
2. (proposing) new system type that covers the maximum bitspace allowed
inside locktag structure, and add a union here to reduce confusion
(encompassing offsetnum but not lockmethodid).
3. pg_lock_status(): I prefer to alter this function to simply return
the follwing:

lockdatum     locktype  <-- bits of locktag structure except for type
pid        integer
locktype    integer
granted    boolean

'lock type' mentioned above as a single datum per lock.  This can be
parsed at the view stage for different types of locks.
So,
select * from pg_locks <--pulls from pg_lock_status filtering on default
lock method
select * from pg_user_locks <--pulls from pg_lock_status filtering on
user lock method

IMO, this is a good setup because it clearly defines the different
types.  This will become even more important if and when more lock types
get added to this system...shared locks for example.  To make this work,
though at the very least a built in cast for int->xid would have to be
added, since there are no casts to or from xid currently.  If doesn't
fly, of course an alternative is to just add more functions to
lockfuncs.c for various locktypes (as well as new lock views).

And finally,
4. a new function in lock.c allowing a lock owned by another process to
be killed.

Merlin






Re: userlock changes for 8.1/8.2

From
Alvaro Herrera
Date:
On Tue, Jan 25, 2005 at 01:51:27PM -0500, Merlin Moncure wrote:

Merlin,

> 2. (proposing) new system type that covers the maximum bitspace allowed
> inside locktag structure, and add a union here to reduce confusion
> (encompassing offsetnum but not lockmethodid).

Please search this message in the archives:

To: Alvaro Herrera <alvherre@dcc.uchile.cl>                                      
Cc: Patches <pgsql-patches@postgresql.org>                                       
Subject: Re: [PATCHES] LockObject patch                                          
Date: Mon, 20 Dec 2004 19:22:30 -0500                                            
From: Tom Lane <tgl@sss.pgh.pa.us>  

-- 
Alvaro Herrera (<alvherre[@]dcc.uchile.cl>)
"Oh, great altar of passive entertainment, bestow upon me thy discordant images
at such speed as to render linear thought impossible" (Calvin a la TV)


Re: userlock changes for 8.1/8.2

From
Tom Lane
Date:
"Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> Ok, you answered my next question.  Part of my confusion here is the
> comments in front of LockAcquire() which explains how userlocks are
> supposed to be mapped to the lock tag.  In the case of userlocks, the
> locktag is basically a hash key, right?

Those are just comments ;-).  You have a hash tag and you can do
anything you like with it ... except make it bigger ... the lockmethod
field is sufficient to keep it from colliding with any system-generated
tags.

> ctid is useless for user locks because an update from a non-cooperating
> client will change it unless the locks become non-cooperative,

[ shrug... ]  Since userlocks are only advisory, a non-cooperating
client can break anything in sight anyway.  I don't find the above
argument convincing.  But in any case, you can use an OID or serial
sequence identifier if you prefer that to CTID.  They're just integers
and it's really up to the user application to define the interpretation
of a userlock tag.

> IOW, a 'user lock' candidate identifier generated by the database
> must be both unique and persistent for the lifetime of the lock.

See above.  The database isn't defining anything here.
        regards, tom lane


Re: userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
Tgl wrote:
> [ shrug... ]  Since userlocks are only advisory, a non-cooperating
> client can break anything in sight anyway.  I don't find the above
> argument convincing.  But in any case, you can use an OID or serial
> sequence identifier if you prefer that to CTID.  They're just integers
> and it's really up to the user application to define the
interpretation
> of a userlock tag.

Right.  My point is that use of CTIDs just too easy to screw up from the
user's perspective, because they change with updates.  I was briefly
toying with a 'auto lock' mode which built the lock from ctid +
tableoid.

So, I'd suggest discouraging the use of ctid, just like the use of OIDs
is discouraged (in fact there is already a disclaimer about using ctid
as a logical identifier in the docs).  Certainly we can't provide a
tighter integration between the user locks and the system columns via
extensions to the grammar, etc.

So it becomes a documentation issue.

Merlin


Re: userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
Alvaro wrote:
> Please search this message in the archives:

right. heh. Well, moving on...

tgl wrote:
> Since subids and offnums are only 16 bits, we could pack all of these
> cases into 64 bits with a 16-bit type identifier to distinguish the
> cases.  That would mean that LOCKTAG doesn't get any bigger than it is
> now, and we'd have plenty of room for expansion still with more types.

Ok, this makes perfect sense, kind of what I was saying only better.

The only thing I can add to it at this point is to reorganize the lock
view(s) correspondingly...should be 1 view for each specific lock type
plus 1 generic one for all locks.   A new datum for the generic lock
type (plus some casts) might be worth considering.

Is it possible for one backend (with superuser privs) to release a lock
held by anotether?

Merlin

Re: userlock changes for 8.1/8.2

From
Tom Lane
Date:
"Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> Is it possible for one backend (with superuser privs) to release a lock
> held by anotether?

As of 8.0 this is not possible for regular locks, because there'd be no
way to update the other backend's internal data structure that shows
what locks it holds.  I think though that there is no corresponding
structure for userlocks and so in principle it could be done for
userlocks.

Whether it's a good idea is a whole 'nother question.  It strikes me
as a foot-gun with no evident redeeming social value.  In particular,
there would most likely be some state inside the client app showing
that it holds this userlock, and so the inability-to-update-state
problem comes right back at that level.

            regards, tom lane

Re: userlock changes for 8.1/8.2

From
"Jim C. Nasby"
Date:
On Tue, Jan 25, 2005 at 08:19:05AM -0500, Merlin Moncure wrote:
> > > [ yawn... ]  Create a table with a "name" column, put some rows in
> it,
> > > lock the rows.
> > 
> > What would guarantee that the OIDs of those rows don't conflict with
> > some other OIDs in the system?
> > 
> > BTW, this becomes a real issue if you're trying to write code that is
> > meant to be incorporated into other PostgreSQL applications, which
> might
> > also be using user_lock. Having a text-based means to identify locks
> > greatly reduces the odds of conflicting with a userlock being used by
> an
> > existing application.
> 
> I prefer sequences to OIDs in virtually every aspect, including this
> one.  However, it would be nice to have system generated unique tuple
> identifier.  There isn't one currently that would fit in the userlock
> restriction of 48 bits.  Any identifier derived from system columns
> probably would take 96-128 bits (for example ctid/tableoid combo).
> 
> IMO, the current behavior is ok, meaning I don't necessarily feel that
> there should be a candidate system key to use for them.  However I would
> discourage the use of OIDs with them.

I believe if there was a way to specify in userlock what table you were
working with that the current 48 bit lock size should be OK for almost
any situation. With the current scheme you could have locks on 65k
tables, any of which could have up to 2^32 rows (has anyone actually
ever exceeded 2^32 rows?). Granted, it's not perfect, but it's better
than what we have now.
-- 
Jim C. Nasby, Database Consultant               decibel@decibel.org 
Give your computer some brain candy! www.distributed.net Team #1828

Windows: "Where do you want to go today?"
Linux: "Where do you want to go tomorrow?"
FreeBSD: "Are you guys coming, or what?"


Re: userlock changes for 8.1/8.2

From
"Merlin Moncure"
Date:
> "Merlin Moncure" <merlin.moncure@rcsonline.com> writes:
> > Is it possible for one backend (with superuser privs) to release a
lock
> > held by anotether?
>
> As of 8.0 this is not possible for regular locks, because there'd be
no
> way to update the other backend's internal data structure that shows
> what locks it holds.  I think though that there is no corresponding
> structure for userlocks and so in principle it could be done for
> userlocks.

Fair enough.  Doesn't seem right to do this for userlocks and not other
locks.

> Whether it's a good idea is a whole 'nother question.  It strikes me
> as a foot-gun with no evident redeeming social value.  In particular,
> there would most likely be some state inside the client app showing
> that it holds this userlock, and so the inability-to-update-state
> problem comes right back at that level.

I'll take you up on this one:
Firstly this is application defined, so who knows what the app is doing.
Now for the more selfish reasons :-)

I'm using the user locks to provide ISAM style pessimistic locks for
postgresql...and they work stupendously good for this, better than any
other commercial isam->rdbms implemention that I've seen...they
generally rely on lock tables (yuck) and/or triggers (double yuck) to
provide equivalent functionality.

Anyways, a lot of these ISAM vendors (like AcuCorp AcuCOBOL for example)
provide service monitoring tools that allow you to disconnect a user or
his locks as an administrative function.  Since users have been know to
do silly things lock a record and then go to lunch, COBOL admins like
the power of being able to relieve them of their locks without having to
resort to killing their connection.  So, from the ISAM point of view,
it's an attractive feature for pg.  I make no claims to merit on
technical grounds however.

Merlin