问题
When using MySQL START TRANSACTION and the decision is made by MySQL to roll back - In the case that a table had an AUTO_INCREMENT column - does the column get... decremented during the roll back?
Or should it?
I am having some issues where the transaction data is being properly rolled back - but it looks like the table was auto incremented and not decremented in the rollback.
# BOTH TABLES START OUT EMPTY // TABLE1 ID is **auto_increment**
START TRANSACTION;
INSERT INTO `TABLE1` (`ID` ,`NAME`) VALUES (NULL , 'Ted'); # MySQL TABLE1 **ID** is Auto incremented to 1
INSERT INTO `TABLE2` (`ID` ,`WRONGVALUE`) VALUES (NULL , 'some value'); # error. This TRANSACTION will not succeed
COMMIT; # Because of the error - this TRANSACTION is now rolled back and Ted is NOT added
Because MySQL will auto_increment the ID on the first table - regardless of if the transaction succeeds or fails - is the standard practice for this to decrement the table yourself?
回答1:
No, auto-increment mechanisms must work outside the scope of transactions, because another user may be inserting to the same table before you finish your transaction. The other user's transaction must be able to allocate the next value, before knowing whether your transaction is using the value you just allocated.
Re your comment: If I may say it more clearly, any change in the scope of a transaction may be rolled back. The auto-increment counter is not rolled back, so it doesn't obey atomicity of transactions. Nor does it obey isolation because another transaction gets the next value even though your transaction hasn't committed yet.
The way auto-increment works means that sometimes, if you insert some rows and then roll back your transaction, the values you allocated with auto-increment are lost forever!
But this is okay. Primary key values must be unique, but they don't need to be consecutive. In other words, they are not row numbers, and you shouldn't use them like that. So you should never need to decrement values created by auto-increment.
回答2:
Disclosure: I am relatively new to SQL so some of this may be wrong. But this is how I understand it. Auto increment must function outside of transactions otherwise you can compromise data. Let us say you have 2 users both trying to connect to your dB. Both are creating accounts. When Account 1 is being created it increments up to 1. Then Account 2 is created and it increments to 2. So far it would look like the following:
- (1, Account1)
- (2, Account2)
- Increment: 2.
Now let us say that Account 2 commits, but Account 1 fails. Now your table looks as follows:
- (2, Account2)
- Increment: 1.
Because you decremented your Auto Increment, you will fail at having a unique value when someone tries to register a new account, because the pair will be:
- (2,Account2)
- Attempting to Insert (2, NewAccount)
Which will fail because 2, the primary key, will not be unique.
If you need to fix your table (for development purposes) you can always run the following code:
ALTER TABLE `DB_NAME`.`TABLE_NAME`
AUTO_INCREMENT = 1 (or some other number);
来源:https://stackoverflow.com/questions/14758625/mysql-auto-increment-columns-on-transaction-commit-and-rollback