Why MySQL does the insert row and then delete it if a rollback is called?
For e.g. with the following code:
declare exit handler for not found rollback;
declare exit handler for sqlwarning rollback;
declare exit handler for sqlexception
BEGIN
select last_insert_id();
rollback;
END;
START TRANSACTION;
INSERT INTO test (text) VALUES ('this_insert_works');
INSERT INTO test (id, text) VALUES (3,'this_insert_fails');
On the following code on a store procedure, if I execute it, and then I execute it again without the last line (it will work) I can see a “missing auto_increment ID” because the row was inserted and then, removed. The select returned returns an ID that doesn’t exists.
How can avoid this behavior?
You can’t avoid this behavior.
Say you have two concurrently-running transactions and they both insert some records into
testinside of a transaction. What will theiridvalues be? What should happen if you commit one but roll back the other?The only feasible option is to increment the table’s auto_increment counter; since each transaction can’t see each other’s rows (but the rows do exist inside of their respective transactions), this is the only way to ensure that they both get a unique id.
While this behavior may appear undesirable, it’s actually there for a very good reason. The only other option would be to lock the entire table when doing an
INSERTinside of a transaction, preventing every other connection from inserting rows into that table at the same time. This would be terrible for performance.