[MDEV-13094] SHOW CREATE TABLE can report non-persistent AUTO_INCREMENT value before server restart Created: 2017-06-14 Updated: 2020-04-23 |
|
| Status: | Confirmed |
| Project: | MariaDB Server |
| Component/s: | Storage Engine - InnoDB |
| Affects Version/s: | 10.2.4 |
| Fix Version/s: | 10.2 |
| Type: | Bug | Priority: | Major |
| Reporter: | Elena Stepanova | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 0 |
| Labels: | None | ||
| Issue Links: |
|
||||||||||||
| Description |
|
|
| Comments |
| Comment by Elena Stepanova [ 2017-06-22 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-05 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
The issue here is that before restart, SHOW CREATE TABLE is not displaying the next value that would be assigned. After restart, it is displayed. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2017-09-05 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
marko, have you noticed that the second INSERT IGNORE does not actually insert anything?
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
elenst, this is somewhat tricky. 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:
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. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I tested the following patch. If we decide to go this way, it would require some more work, because the persisted AUTO_INCREMENT value is the last assigned value, while SHOW CREATE TABLE should display the next usable value. At the very least, we should take auto_increment_increment and auto_increment_offset into account, similar to how ha_innobase::get_auto_increment() works.
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-06 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Some further thoughts:
One option would be to introduce an interface for reporting the persisted state of the AUTO_INCREMENT, instead of changing the operation of SHOW CREATE TABLE. This would seem to only make sense if implemented for all storage engines that support persistent AUTO_INCREMENT. I recommend simply documenting the current behaviour. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ian Gilfillan [ 2017-09-20 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I don't understand how to document this from a user perspective. SHOW CREATE TABLE does not seem to be as issue - it will correctly display the next value in both cases after the failed INSERT IGNORE, both before and after a restart. The issue is that there is a persistent autoinc value (with no interface to view it), and that after a server restart, this persistent value is being used to set the actual autoinc value. So, if I understand:
Is this correct? Is there any way for the user to view the persistent autoinc value? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-09-20 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
greenman, your interpretation sounds correct to me. The regression would be that after a failed INSERT IGNORE and a restart, there would be a "gap" in the AUTO_INCREMENT value. Another case where you can get such a "gap" is a user-initiated ROLLBACK or ROLLBACK TO SAVEPOINT. But also that requires a server restart. So, this regression (gap after restart) would seem to be a desired property of | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ian Gilfillan [ 2017-09-25 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
I have documented the current behaviour, though this still seems undesirable and perhaps it can be solved in another way. Without knowledge of the underlying implementation, does the following logic hold?
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Marko Mäkelä [ 2017-10-04 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
greenman, I think that the main use case of persistent autoinc is a guarantee that the same values are not reassigned after server restart (except if the counter was reset with ALTER TABLE). It just occurred to me that the MyISAM and Aria engines (which featured persistent AUTO_INCREMENT from day one) have a uniquely defined AUTO_INCREMENT value: that of the last committed record. With table-level locking and with no support for rollback (except in Aria crash recovery), this works. InnoDB allows concurrent modifications to the table, and it supports rollback. Therefore, the AUTO_INCREMENT is necessarily different. The value that is persisted in the first root page of the table is the maximum value that was used in an INSERT or UPDATE. Even if the operation was rolled back, that value will remain. Another AUTO_INCREMENT is the value that is reported to the user in the SHOW CREATE TABLE statement. And yet another one is the LAST_INSERT_ID(). In InnoDB, these are non-persistent. elenst, what would you think if we extended INFORMATION_SCHEMA.INNODB_SYS_TABLESTATS with a column that shows the persistent auto-increment value? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Ian Gilfillan [ 2018-10-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Marko's suggestion seems like a fairly quick and easy approach. Are there any objections to it? | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Comment by Elena Stepanova [ 2018-10-08 ] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Sorry, I missed the question addressed to me back then. We can add all kinds of columns to InnoDB I_S tables, I don't see how it will solve anything. People don't search for the auto-increment value for fun or out of curiosity, much less should they care about the dark secrets of implementation – what's "persistent" and what not. They should see the value which is actually true now, and it should be consistent. Now the obvious discrepancy in SHOW CREATE TABLE breaks simple consistency checks (tables before and after server restart differ), but it's not limited to it. AUTO_INCREMENT in SHOW CREATE TABLE is not cosmetics, it shows what happens next, and the behavior of auto-increment becomes inconsistent after the scenario above. If you keep normally inserting into the table before the restart, it will insert 4 etc. If you insert after restart, it will insert 101 etc. That said, I am not going to argue now against whichever decision is made, I'll leave it to be resolved by the natural course of events. We have already been questioned why such unexpected jumps can occur. So far it was by Monty, who, I suppose, relayed a question from customers; I expect it to happen again and eventually present itself in a form of an official customer request which we won't be able to ignore. |