elenst, this is somewhat tricky.
The persistent InnoDB AUTO_INCREMENT value that was implemented in MDEV-6076 is not transactional; it is only crash-safe.
If a transaction or a part of it is rolled back, the persistent AUTO_INCREMENT counter will not be rolled back. When the INSERT IGNORE attempts to insert the record (pk,i)=(100,1) a duplicate key i=1 into the unique secondary index, it will already have performed the following steps:
- Acquire a record lock on the PRIMARY KEY (pk=100).
- Write undo log for rolling back the insert (100,1).
- Update the persistent AUTO_INCREMENT value to 101, and insert the record (100,1) into the PRIMARY KEY.
- Acquire a record lock on the UNIQUE KEY (i=1).
- Try to insert the record (i,pk)=(1,100) into the unique index. This will fail due to the pre-existing key (i,pk)=(1,1).
- To resolve the duplicate key error, roll back the latest row from the undo log. (This is a no-op for the UNIQUE KEY, because no record (i,pk)=(1,100) exists there.)
The mini-transaction that inserted the record (100,1) into the PRIMARY KEY was committed. If you want to avoid observing a change to the persistent AUTO_INCREMENT sequence, the only solution would be to kill the server before the INSERT IGNORE transaction was committed, and hope that the server did not flush the redo log for example because a transaction in another connection ended, or because InnoDB decided to perform a redo log checkpoint.
Basically the main guarantee that we give is that if a transaction was persistently committed, changes to the auto-increment counter will be persisted as well, even if the server was killed and restarted after the transaction commit.
Note that in InnoDB, a rollback includes a commit. First, InnoDB would apply the undo log of the transaction backwards, basically emptying the set of modifications made by the transaction, and then it would commit that empty transaction. The innodb_flush_log_at_trx_commit setting affects the final commit step of rollback too.
Because there is no undo logging for the persistent AUTO_INCREMENT sequence, the AUTO_INCREMENT will stay where it was left, even if there was a partial or full rollback of the transaction.
If we changed the LAST_INSERT_ID() to reflect the last reserved AUTO_INCREMENT value instead of the last inserted value, a lot of things would break.
In my opinion, the only thinkable change here might be to change SHOW CREATE TABLE so that it will report the actual persisted AUTO_INCREMENT value, with the disclaimer that if the server is killed and the redo log was not yet flushed up to the point where the persistent AUTO_INCREMENT was last changed, you could see a different value after restart.
I have to disable the check for auto-increment in upgrade tests with 10.2+ old server for now. Need to re-enable it after the bug is fixed.