Reputation: 20997
I need a little help with SELECT FOR UPDATE
(resp. LOCK IN SHARE MODE
).
I have a table with around 400 000 records and I need to run two different processing functions on each row.
The table structure is appropriately this:
data (
`id`,
`mtime`, -- When was data1 set last
`data1`,
`data2` DEFAULT NULL,
`priority1`,
`priority2`,
PRIMARY KEY `id`,
INDEX (`mtime`),
FOREIGN KEY ON `data2`
)
Functions are a little different:
priority1
; sets data1
and mtime
priority2
; sets data1
and mtime
They shouldn't modify the same row at the same time, but the select may return one row in both of them (priority1
and priority2
have different values) and it's okay for transaction to wait if that's the case (and I'd expect that this would be the only case when it'll block).
I'm selecting data based on following queries:
-- For the first function - not processed first, then the oldest,
-- the same age goes based on priority
SELECT id FROM data ORDER BY mtime IS NULL DESC, mtime, priority1 LIMIT 250 FOR UPDATE;
-- For the second function - only processed not processed order by priority
SELECT if FROM data ORDER BY priority2 WHERE data2 IS NULL LIMIT 50 FOR UPDATE;
But what I am experiencing is that every time only one query returns at the time.
So my questions are:
SELECT ... FROM (SELECT ...) WHERE ... IN (SELECT)
would be appreciated )?ORDER BY ... LIMIT ...
cause any issues?Upvotes: 7
Views: 4503
Reputation: 1
All points in accepted answer seem fine except below 2 points: "whatever was going to be returned by the Select will be the rows that get locked." & "Can indexes and keys cause any issues? but they shouldn't cause any issues with obtaining a lock."
Instead all the rows which are internally read by DB during deciding which rows to select and return will be locked. For example below query will lock all rows of the table but might select and return only few rows: select * from table where non_primary_non_indexed_column = ? for update Since there is no index, DB will have to read the entire table to search for your desired row and hence lock entire table.
If you want to lock only one row either you need to specify its primary key or an indexed column in the where clause. Thus indexing becomes very important in case of locking only the appropriate rows.
This is a good reference - https://dev.mysql.com/doc/refman/5.7/en/innodb-locking-reads.html
Upvotes: 0
Reputation: 106
Key things to check for before getting much further:
Order and limit will have no impact on the issue you're experiencing as far as I can tell, whatever was going to be returned by the Select will be the rows that get locked.
To answer your questions:
Upvotes: 4