Reputation: 11608
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?
Upvotes: 2
Views: 390
Reputation: 169478
You can't avoid this behavior.
Say you have two concurrently-running transactions and they both insert some records into test
inside of a transaction. What will their id
values 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 INSERT
inside of a transaction, preventing every other connection from inserting rows into that table at the same time. This would be terrible for performance.
Upvotes: 3