0

I have the following simple two-selects sequence within a stored procedure:

SELECT * FROM mytable WHERE <conditions>;
SELECT id FROM mytable ORDER BY id DESC LIMIT 1;

where id is the primary key of mytable.

The overall purpose is to select some rows from mytable (including the newest ones - ie the ones with the heighest id values) and then, with the second select, get the id of the last/newest row in the same table.

Question: how do I ensure that no new records gets inserted between the first and the second select?

I was going to use:

TRANSACTION
select <1..> FOR UPDATE;
select <2..>;
COMMIT

but will that always work and is there a better way?

Or can do something different to achieve the goal of getting the heighest id value from the first select without having the second select?

frigel
  • 77
  • 1
  • 5
  • I believe you want a table lock: https://dev.mysql.com/doc/refman/5.5/en/lock-tables.html *I may be wrong though – JNevill Oct 24 '18 at 13:57

1 Answers1

0

When you haven't changed your isolation level, you are using the default of REPEATABLE READ which already solves this problem.

To check which isolation level you're using you can execute the following query:

SELECT @@global.tx_isolation, @@session.tx_isolation;

The global value is the default value for newly created sessions. The sessions value is of course the value you are currently using.

You can set it explicitly for your session with

SET SESSION tx_isolation='REPEATABLE-READ';

With REPEATABLE-READ you can simply do this:

START TRANSACTION;
SELECT * FROM mytable WHERE <conditions>;
SELECT id FROM mytable ORDER BY id DESC LIMIT 1;
COMMIT;

When another session inserts rows into the table during your 2 selects, this row won't show up inside your transaction.

I posted more details about isolation levels in my answer here.

If you want to combine the two queries into one, you could do this:

SELECT m.*, s.maxid 
FROM mytable m 
CROSS JOIN (SELECT MAX(id) AS maxid FROM mytable) s 
WHERE <conditions>;
fancyPants
  • 50,732
  • 33
  • 89
  • 96
  • 1
    Just to be clear, during **your** repeatable-read transaction other rows may be inserted, updated, or deleted by other processes. However, your transaction won't see them. If you really want to prevent other processes to make changes, then lock the table. – The Impaler Oct 24 '18 at 17:56
  • @TheImpaler Correct, yes. But **my** transaction is the standard behaviour :) – fancyPants Oct 24 '18 at 21:03