Hi Joe,

Thanks for your reply.  Actually, in my experience (and according to the docs), if you 
select 'for
update' or 'lock in share mode', you _can_ lock non-existence of a row for inserts.  
In that case I
think the 'gap' where the row would be is locked, and attempts to insert the row from 
another
transaction will block or fail (until the first one does a commit or a rollback).  
Perhaps I'm
misunderstanding what's happening?

Unfortunately, what I'm trying to do is try to have one transaction 'lock' the 
non-existence of a
row with a select, and another wait until the lock is released--also with a select.  
I've considered
doing what you propose with a separate lock table, and may still do just that, but 
first wanted to
see if I can accomplish the same thing with some clever DB manipulation.

Thanks!

Alex

-----Original Message-----
From: Joe Shear [mailto:[EMAIL PROTECTED] 
Sent: Tuesday, January 20, 2004 11:00 AM
To: Zeltser, Alex
Cc: [EMAIL PROTECTED]
Subject: RE: InnoDB locking 'non-existence' of a row


hi, 
Selecting a non-existent row won't acquire any locks that prevents inserts from 
happening.  One way
to accomplish what you want is to create a separate insert lock table consisting of a 
table name and
a lock counter.  Add a row for each table that you want to have these insert locks on, 
and before
performing any inserts, either update the corresponding row in the insert lock table 
or select it
for an update. 

joe

On Tue, 2004-01-20 at 10:01, Zeltser, Alex wrote:
> Hi Chris,
> 
> Thanks for the response and the suggestions.  Doesn't SERIALIZABLE 
> level just add 'LOCK IN SHARE MODE' to your SELECTs, but other than 
> that works just like the default REPEATABLE READ level?  I've tried by 
> example below using 'LOCK IN SHARE MODE' instead of 'FOR UPDATE', but 
> the results were the same.
> 
> Is there any way to make the second session block when both it and the 
> first one are 'locking' non-existence of a row?
> 
> Thanks in advance,
> 
> Alex
> 
> -----Original Message-----
> From: Chris Nolan [mailto:[EMAIL PROTECTED]
> Sent: Friday, January 16, 2004 4:55 PM
> To: Zeltser, Alex
> Cc: [EMAIL PROTECTED]
> Subject: Re: InnoDB locking 'non-existence' of a row
> 
> 
> Hi Alex!
> 
> On Sat, 2004-01-17 at 05:50, Zeltser, Alex wrote:
> > Hi,
> > 
> > I wanted to take advantage of the InnoDB 'gap' locking to lock
> > 'non-existence' of a row, the way the manual recommends.  I tried to 
> > do this by using 'select ... for update', using the 'mysql' client 
> > from two separate sessions as shown below:
> > 
> > Session 1:
> > > set AUTOCOMMIT=0;
> > > begin;
> > > select * from T where A = 'NOT_THERE' for update;
> > 
> > Session 2:
> > > set AUTOCOMMIT=0;
> > > begin;
> > > select * from T where A = 'NOT_THERE' for update;
> > 
> > What I'd hoped to see was the 'select' statement in Session 2 block
> > until either a commit or a rollback was performed in Session 1.  
> > Unfortunately, it didn't work that way.  The 'select's in both 
> > sessions returned right away, and it was only the subsequent 
> > 'insert's, 'update's and 'delete's that blocked.  I can understand the 
> > rationale behind this behavior, but unfortunately it doesn't help me 
> > with my problem.  I'd like to be able to reliably check for existence 
> > of a record from two concurrent sessions and have the 'select' in the 
> > 'second' session block until the first session is either committed or 
> > rolled back.  Is there a way to accomplish this somehow?
> > 
> InnoDB's next-key locking is a bit different to this - it ensures that 
> phantom rows do not appear. This is good for application writers and 
> for MySQL itself, as phantom rows appearing would break MySQL's 
> replication.
> 
> Basically, InnoDB will place locks on the various index structures 
> involved in your query around the rows that have been returned bt a 
> SELECT ... FOR UPDATE. As your selects return nothing, InnoDB doesn't 
> find any index sections to place any locks on.
> 
> Perhaps you should look at using the SERIALIZABLE level of transaction 
> isolation.
> 
> Regards,
> 
> Chris
> 
> > I know I can just try to insert the record and check for duplicates,
> > but is there a way to accomplish it with 'select's?
> > 
> > Thanks in advance,
> > 
> > Alex Zeltser
> > 
> > --
> > MySQL General Mailing List
> > For list archives: http://lists.mysql.com/mysql
> > To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]
> > 
-- 
Joe Shear <[EMAIL PROTECTED]>


--
MySQL General Mailing List
For list archives: http://lists.mysql.com/mysql
To unsubscribe:    http://lists.mysql.com/[EMAIL PROTECTED]

Reply via email to