Mysql Myisam re-using auto-incremented ids that are deleted - mysql

I have a table: test
id int(10) auto-increment
name char(36)
Now let us say my WHOLE table it filled from ID 1000 => max unique id number.
Id 1 - 1000 = deleted previously.
Question 1; WILL mysql re-use these deleted id's?
Question 2; If not, how to I go about having auto-increment or whatever to re-use unique identifier that does not exist in table?
The reason I am asking, is that my table will consist of alot of entries, and that alot of entries will be deleted all the time. What happens when I "run-out-of-id" when using auto-increment?
Thanks for any enlightment on this :)
-Tom

WILL mysql re-use these deleted id's?
When mysqld starts, it determines the next value for every AUTO_INCREMENT column by finding the maximum of the incumbent records (and adding 1). Therefore, if you delete the record with the highest value and restart the server, the deleted id will indeed be reused.
Otherwise, values will only be reused if you manually alter the next AUTO_INCREMENT value (this is not recommended as it is not concurrency-safe):
ALTER TABLE foo AUTO_INCREMENT = 12345;
If not, how to I go about having auto-increment or whatever to re-use unique identifier that does not exist in table?
Generally speaking, you don't: consider redesigning your data structure so that inserts/deletes do not happen in this fashion, or else use a larger integer type (BIGINT UNSIGNED is 8 bytes, so can go up to 2^64 or ~10^19).
What happens when I "run-out-of-id" when using auto-increment?
As stated in the manual:
Use the smallest integer data type for the AUTO_INCREMENT column that is large enough to hold the maximum sequence value you will need. When the column reaches the upper limit of the data type, the next attempt to generate a sequence number fails.

No, MySQL won't reuse the IDs from deleted records
Do you really need to? If the type of your autoincrement column is BIGINT, you've got 18446744073709551615 possible IDs

you need to reset the autoincrement, Autoincrement just keep incrementing and won't go back at least if you don't set it.
alter table tablename auto_increment=value
like this
mysql> alter table t1 auto_increment=200;
Query OK, 202 rows affected (0.04 sec)
Records: 202 Duplicates: 0 Warnings: 0
EDIT:
if you delete some records, the auto_increment will be "last value+1", it doesn't matter what you do, only if you delete the full table you'll be able to 'start over'.
The best would be with a trigger, but triggers can't alter tables (http://dev.mysql.com/doc/refman/5.0/en/create-trigger.html)
So your last option is a store procedure take a look here: Is it possible to alter a table in mySql via stored procedures?
Which is not recommended.

Related

Does the MySQL Auto Increment Column Need to Be Unique or a Primary Key

I was developing a database in SQL Server where I was using an identity column as a seed for a primary key field. The intention was to reset the identity to 1 at the beginning of every year. This would allow us to create a PK of the Year - Identity Column.
Create Table Issues (
IssueID AS RIGHT(CONVERT(VARCHAR, Year(getdate()), 4),2) + '-' + RIGHT(REPLICATE('0', 2) +
CONVERT(VARCHAR, RecordID),3) NOT NULL PRIMARY KEY,
RecordID int Identity (1,1),.........)
The result would be
IssueID RecordID
20-001 1
20-002 2
20-003 3
21-001 1
etc....
Now I've been told we are going to use a MySQL database instead.
Can an Auto-Increment field in MySQL contain duplicate values like it can in SQL Server?
If Not, how can I do what I need to do in MySQL?
In MySQL, you can't use the default auto-increment feature for what you describe, a incrementing value that starts over per year.
This was a feature of the MyISAM storage engine years ago. An auto-increment that was the second column of a multi-column primary key would start counting from one for each distinct value in the first column of the PK. See the example under "MyISAM Notes" on this page: https://dev.mysql.com/doc/refman/8.0/en/example-auto-increment.html
But it's considered not a good idea to use MyISAM because it does not support ACID. In general, I would find another way of solving this task. I would not use MyISAM.
In InnoDB, there's no way the table will generate a value that is a duplicate of a value currently in the table, or even a value less than the maximum value previously generated for that table. In other words, there's no way to "fill in the gaps" using auto-increment.
You can use ALTER TABLE mytable AUTO_INCREMENT=1 to reset the counter, but the value you set it will automatically advance to the max value currently in the table + 1.
So you'll have to generate it using either another table, or else something other than the MySQL database. For example, I've seen some people use memcached, which supports an atomic "increment and return counter" operation.
Another thing to consider: If you need a row counter per year, this is actually different from using MySQL's auto-increment feature. It's not easy to use the latter as a row counter. Besides, what happens if you roll back a transaction or delete a row? You'd end up with non-consecutive RecordId values, with unexplained "gaps." It's also a fact about the auto-increment feature that it guarantees that subsequent id's will be greater, but it does not guarantee to generate all values consecutively. So you'll get gaps eventually anyway.
In MySQL a table can have only one auto_increment column and this column must be a part of the primary key. See details here.
Technical workaround for your task would be creating of a table with a single auto_increment column, and you can obtain auto_increment value by inserting a record into this table and immediately calling standard MySQL function last_inser_id(). When time comes you should truncate the table - in this case the auto_increment count will be reset.

Insert rows in table without affecting AUTO_INCREMENT in MariaDB

I have a table with a bunch of rows whose ID's are numbers with value less than 20,000,000. The table structure looks like this:
CREATE TABLE records(
id int(11) not null AUTO_INCREMENT,
... more data columns ...
) ENGINE=InnoDB AUTO_INCREMENT=16432352 DEFAULT CHARSET=utf8;
A system that is out of my control inserts rows in this table and the database insert those records with a generated ID.
But, I need to insert records in this table with very big ID's (starting 50,000,000). Also, it's important to note that the uncontrolled system inserts few records, such that the records I'm going to insert never collides with the records of the uncontrolled system.
Making some tests I realized that when I insert a record with a very vig ID, the AUTO_INCREMENT value jumps to that very big ID. For example:
First, I check the initial_auto_increment value:
SHOW TABLE STATUS FROM my-database like 'records';
... the auto_increment value looks like this:
# Name, ... , Auto_increment, ...
'record', ... , '16432352', ...
Next, I insert the record with a very big ID.
INSERT INTO records (id, ...) VALUES(679456755, ...);
Then, checking again the auto_increment value:
SHOW TABLE STATUS FROM my-database like 'records';
.. the final result look like this:
# Name, ... , Auto_increment, ...
'record', ... , '679456756', ...
My question is: How can I temporarily disable the AUTO_ICREMENT feature in such way that my records with very big ID's don't mess around with the AUTO_INCREMENT value of the table?
PS. I'm using MariaDB 10.
Edit: I changed the numbers, but the question is the same.
MySQL and MariaDB actually enforce the restriction AUTO_INCREMENT > MAX(id)
See ALTER TABLE Syntax
You cannot reset the counter to a value less than or equal to the value that is currently in use. For both InnoDB and MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is reset to the current maximum AUTO_INCREMENT column value plus one.
You can use ALTER TABLE to set the AUTO_INCREMENT to any value higher than MAX(id) if you would like to store higher values, however you cannot set it to a lower value than one of the rows currently in the table.
If you need to create rows in a "gap", with lower IDs than the AUTO_INCREMENT value, you would need to explicitly specify the id value in your INSERT. But if a process beyond your control is inserting rows and not specifying the IDs then they are always going to obtain IDs higher than everything else currently in the table.
The only thing I can suggest, if you are able to adjust what IDs are used for what, is that you reserve low IDs for your purposes (so use, say, 1 to 10,000 instead of 50,000,000 to 50,009,999), set the AUTO_INCREMENT to 10,001 and then let the outside process use the higher IDs - this would work just fine provided you don't run out of space.
For a longer term solution, consider switching to UUIDs - though you would need to modify the process that is outside your control for this.
You can set the AUTO_INCREMENT to any value you please:
ALTER TABLE records AUTO_INCREMENT = ?
Though I'd strongly recommend burying records at high ID numbers. Usually lower is better, or just mixing them in with regular records. Being obsessive about these things leads to conflict later on when your assumptions end up being mistaken.

Can i adjust the value of an auto-incremented field in the database automatically?

Can i adjust the value of an auto-incremented field in the database automatically?
I have a table called "post" which has a field called "pid" which is set to auto-increment.
Posts from this table may be deleted by the user at a later time, but the auto- incremented value will not be adjusted. Is there a way to adjust the pid field everytime posts are deleted?
for eg:If i have 4 entries: pid=1,2,3,4(pid-auto-increment)
Now if i delete 2, is there a way to update 3 to 2 and 4 to 3 and so on ?
Why would you need to adjust the auto-increment? Each post is uniquely identified using the pid and if that is to change, then the whole DB structure will fail. The idea of the auto-increment is based on this principle and that you don't have to worry about assigning numbers yourself.
If deleting a record is a problem, then you might want to keep it in the database and flag it as deleted. They you can use this flag to show / hide from the users.
Deletion from end
You can manually set AUTO_INCREMENT of a table to a specified value via
ALTER TABLE tbl AUTO_INCREMENT = val;
See Using AUTO_INCREMENT in MySQL manual.
This solves deletion from end – before adding new rows, set AUTO_INCREMENT to 0 and it will be automatically set to current maximum plus one. Newly inserted rows will occupy the same IDs as the deleted ones.
Deletion from anywhere – renumbering
It is possible to manually specify value of the field having AUTO_INCREMENT. AUTO_INCREMENT is ignored them. If you specify a value already used, unique constraint will abort the query. If you specify a value that is bigger than the current maximum, AUTO_INCREMENT automatically set to this one plus one.
If you do not want to manually renumber the records, write a script for that, nor mess with stored procedures, you can use user-defined variables:
SET #id = 0;
UPDATE tbl SET id = #id := #id + 1 ORDER BY id;
SET #alt = CONCAT('ALTER TABLE tbl AUTO_INCREMENT = ', #id + 1);
PREPARE aifix FROM #alt;
EXECUTE aifix;
DEALLOCATE PREPARE aifix;
Example use
http://www.paulwhippconsulting.com.au/webdevelopment/31-renumbering-an-qorderingq-field-in-mysql
http://www.it-iss.com/mysql/mysql-renumber-field-values/
For more info see my answer to a related question.
Warning – this may be harmful!
Usually there is no need to renumber the records. Actually it may be harmful as you may have dangling references to the old record somewhere (possibly outside the DB) and they now become valid again, which could cause confusion. This is why AUTO_INCREMENT attribute of the table is not decremented after a row is deleted.
You should just delete the unwanted records and stop worrying about the holes. They are just in the numbering of the records, purely logical, physically they don’t need to exist in the storage. No space wasted in the long time perspective. For some time the storage really has holes. You can let the DB engine get rid of them by OPTIMIZE TABLE tbl or ALTER TABLE tbl ORDER BY column.

General MYSQL Database understanding

Lets say database has a table which has only two columns of ID which is Auto increment and name which is text. When we first add 2 names, then delete both of the names, next time again enter another name, the ID count starts from number 3 while it should start with number 1.
Question is that is there any way to reset the ID so that it starts from 0 once all values of ID's are removed instead of continuing increment from the last ID number that was removed?
Here's the SQL query to reset the AUTO_INCREMENT value:
ALTER TABLE tablename AUTO_INCREMENT = 0
You can use Truncate.
TRUNCATE TABLE yourtable;
It is similar to deleting all rows of your table but has some differences including resetting auto-increment to 0.
Yes you can
ALTER TABLE mytable AUTO_INCREMENT = 0
But why bother? There are plenty of numbers in the universe or even in 32 bits!
I think this will do what you are looking for.
ALTER TABLE table_name AUTO_INCREMENT = 1;
ALTER TABLE yourtable AUTO_INCREMENT = 1
There sure is!
ALTER TABLE 'mytable' AUTO_INCREMENT = 0;
This will reset the auto increment back down to 0 and continue from there.
A general note from MySQL-dev:
You cannot Reset the counter to a value less than or equal to any that have already been used. For MyISAM, if the value is less than or equal to the maximum value currently in the AUTO_INCREMENT column, the value is Reset to the current maximum plus one. For InnoDB, if the value is less than the current maximum value in the column, no error occurs and the current sequence value is not changed.

Auto Increment Problem in Mysql

I created a table and set a field to auto increment some thing like this:
CREATE TABLE t1(id BIGINT NOT NULL PRIMARY KEY AUTO_INCREMENT) ENGINE = MyISAM AUTO_INCREMENT = 123456;
But to some reason i deleted some of the rows in the table.
Now the question is when i insert new rows in the table the new rows should be assigned id's of the rows which have been deleted rather than assigning new id's.
I do not want to reset all the id's
How can i do this??
Help appreciated:)
Sorry to say, but that is not the use of AUTO_INCREMENT. If you want to re-use id's, then you would have to write your own trigger functions, and doing this is generally considered bad practice.
Imagine you were on id 50,000, and deleted an entry with id 1... would you really want the next record you add to re-use id 1?
The whole point of AUTO_INCREMENT is to auto increment...
You can explicitly assign these ids though and mysql will allow it.
You are going to have to do this manually rather than rely on MySQL to do it for you. The AUTO-INCREMENT flag keeps an integer that is incremented upon every insert statement and is assigned as the PK of the subsequent insert. Unless you want to write an update trigger that resets this value to the lowest non-used integer, I would suggest processing this in a server-side scripting language.
In any case, though, why is using the auto increment value a problem?
To reset the autoincrement value, you can use
ALTER TABLE t1 AUTO_INCREMENT=1
The next inserted record will use ID 1.
This might be something you're after.
alter table Users AUTO_INCREMENT=0;
This will reset the auto_increment back to 0 + whatever the current highest id is.
if you have 30, your next entry would be 31