SQL Server auto-identity unexpected reset/value - sql

SQL Server
Version: 12.0.5556.0
Problem: SQL Server genereated an unexpected identity or did a reset on the auto-identity value
Information: I have a customer system which is running SQL Server 12.0.556.0 where, while testing phase I generated some test data which was deleted when the system was going live. So the identity value on this table startet at ~34.000 when the system was going into production in 2018.
Now after 2 years the identity value is at ~90.000, but a few days ago an entry with the identity 1 was created. When i query the table with select IDENT_CURRENT('MyTable') it is showing a value of 90182.
Now to my question, is there any reason why SQL Server would suddenly change the identity value to 1 and then jump back to the current identity value of ~90.000?

One possibility is that someone set identity_insert to ON for the table and inserted the row.
Otherwise, you cannot insert an explicit value for an identity column.
And, identity is guaranteed to be an increasing value (although there may be gaps) when generated automatically.

Related

SQL server auto increment field [duplicate]

In one of my tables Fee in column "ReceiptNo" in SQL Server 2012 database identity increment suddenly started jumping to 100s instead of 1 depending on the following two things.
if it is 1205446 it is jumps to 1206306, if it is 1206321, it jumps to 1207306 and if it is 1207314, it jumps to 1208306. What I want to make you note is that the last three digits remain constant i.e 306 whenever the jumping occurs as shown in the following picture.
this problem occurs when I restart my computer
You are encountering this behaviour due to a performance improvement since SQL Server 2012.
It now by default uses a cache size of 1,000 when allocating IDENTITY values for an int column and restarting the service can "lose" unused values (The cache size is 10,000 for bigint/numeric).
This is mentioned in the documentation
SQL Server might cache identity values for performance reasons and
some of the assigned values can be lost during a database failure or
server restart. This can result in gaps in the identity value upon
insert. If gaps are not acceptable then the application should use its
own mechanism to generate key values. Using a sequence generator with
the NOCACHE option can limit the gaps to transactions that are never
committed.
From the data you have shown it looks like this happened after the data entry for 22 December then when it restarted SQL Server reserved the values 1206306 - 1207305. After data entry for 24 - 25 December was done another restart and SQL Server reserved the next range 1207306 - 1208305 visible in the entries for the 28th.
Unless you are restarting the service with unusual frequency any "lost" values are unlikely to make any significant dent in the range of values allowed by the datatype so the best policy is not to worry about it.
If this is for some reason a real issue for you some possible workarounds are...
You can use a SEQUENCE instead of an identity column and define a smaller cache size for example and use NEXT VALUE FOR in a column default.
Or apply trace flag 272 which makes the IDENTITY allocation logged as in versions up to 2008 R2. This applies globally to all databases.
Or, for recent versions, execute ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFF to disable the identity caching for a specific database.
You should be aware none of these workarounds assure no gaps. This has never been guaranteed by IDENTITY as it would only be possible by serializing inserts to the table. If you need a gapless column you will need to use a different solution than either IDENTITY or SEQUENCE
This problems occurs after restarting the SQL Server.
The solution is:
Run SQL Server Configuration Manager.
Select SQL Server Services.
Right-click SQL Server and select Properties.
In the opening window under Startup Parameters, type -T272 and click Add, then press Apply button and restart.
From SQL Server 2017+ you could use ALTER DATABASE SCOPED CONFIGURATION:
IDENTITY_CACHE = { ON | OFF }
Enables or disables identity cache at the database level. The default
is ON. Identity caching is used to improve INSERT performance on
tables with Identity columns. To avoid gaps in the values of the
Identity column in cases where the server restarts unexpectedly or
fails over to a secondary server, disable the IDENTITY_CACHE option.
This option is similar to the existing SQL Server Trace Flag 272,
except that it can be set at the database level rather than only at
the server level.
(...)
G. Set IDENTITY_CACHE
This example disables the identity cache.
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE=OFF ;
I know my answer might be late to the party. But i have solved in another way by adding a start up stored procedure in SQL Server 2012.
Create a following stored procedure in master DB.
USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[ResetTableNameIdentityAfterRestart]
AS
BEGIN
begin TRAN
declare #id int = 0
SELECT #id = MAX(id) FROM [DatabaseName].dbo.[TableName]
--print #id
DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, #id)
Commit
END
Then add it in to Start up by using following syntax.
EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';
This is a good idea if you have few tables. but if you have to do for many tables, this method still works but not a good idea.
This is still a very common issue among many developers and applications regardless of size.
Unfortunately the suggestions above do not fix all scenarios, i.e. Shared hosting, you cannot rely on your host to set the -t272 startup parameter.
Also, if you have existing tables that use these identity columns for primary keys, it is a HUGE effort to drop those columns and recreate new ones to use the BS sequence workaround. The Sequence workaround is only good if you are designing the tables new from scratch in SQL 2012+
Bottom line is, if you are on Sql Server 2008R2, then STAY ON IT. Seriously, stay on it. Until Microsoft admits that they introduced a HUGE bug, which is still there even in Sql Server 2016, then we should not upgrade until they own it and FIX IT.
Microsoft straight up introduced a breaking change, i.e. they broke a working API that no longer works as designed, due to the fact that their system forgets their current identity on a restart. Cache or no cache, this is unacceptable, and the Microsoft developer by the name of Bryan needs to own it, instead of tell the world that it is "by design" and a "feature". Sure, the caching is a feature, but losing track of what the next identity should be, IS NOT A FEATURE. It's a fricken BUG!!!
I will share the workaround that I used, because My DB's are on Shared Hosting servers, also, I am not dropping and recreating my Primary Key columns, that would be a huge PITA.
Instead, this is my shameful hack (but not as shameful as this POS bug that microsoft has introduced).
Hack/Fix:
Before your insert commands, just reseed your identity before each insert. This fix is only recommended if you don't have admin control over your Sql Server instance, otherwise I suggest reseeding on restart of server.
declare #newId int -- where int is the datatype of your PKey or Id column
select #newId = max(YourBuggedIdColumn) from YOUR_TABLE_NAME
DBCC CheckIdent('YOUR_TABLE_NAME', RESEED, #newId)
Just those 3 lines immediately before your insert, and you should be good to go. It really won't affect performance that much, i.e. it will be unnoticeable.
Goodluck.
There are many possible reasons for jumping identity values. They range from rolled back inserts to identity management for replication. What is causing this in your case I can't tell without spending some time in your system.
You should know however, that in no case you can assume an identity column to be contiguos. There are just too many things that can cause gaps.
You can find a little more information about this here: http://sqlity.net/en/792/the-gap-in-the-identity-value-sequence/

Identity increment was jumping in sql server database ( Amazon server)

I am using Sql server 2012(Amazon RDS). I have a table which has an identity column in it.At the beginning Identity column starts from 1,2 and so on and adding identity smoothly, but suddenly it jumps from 17018 to 27011. What could be the reason. Please assist.
thanks,
Sella
Restarting server instance may cause this.
See this
Any of these things can cause a jump in the identity column:
An insert into the table that is later rolled back
An error when inserting into the table (like unique constraint violation)
A delete from the table
Someone use IDENTITY INSERT ON to set a value for the identity column. If that value is bigger than the current value, the sequence will resume at that.
A server restart
In general, you shouldn't expect identity columns to increment by 1. Treat the value as random. The only difference between identity and a true random is that it's guaranteed to be increasing in value.

SQL Server: "Cannot insert the value NULL into column" - on identity column

I am inserting data into a table with an identity column called unique_id. I am leaving the unique_id column out of the insert, assuming that the value will then be seeded from the identity configuration on the column.
Insert statement:
INSERT INTO table_name (column_1, column_2, column_3, processed_dt)
VALUES ('A', 'B', 'C', GETDATE());
Error:
Cannot insert the value NULL into column 'unique_id', table 'db.dbo.table_name'; column does not allow nulls. INSERT fails.
When I double click on the unique_id column in SQL Server Management Studio, I see that the following values are set:
Identity: true
Identity Seed: 1
Identity Increment: 1
What other configuration may be wrong to cause the identity seed to not be used automatically?
UPDATE:
Based on some of the recommendations I am seeing, I want to add that this schema was converted by our vendor from Oracle into SQL Server. I'm guessing that part of that process must of included converting Oracle Sequences into SQL Server Identity columns. Something being "broken" with the identity column is certainly a possibility.
I'm definitely on the correct database, table, and column. The Identity on this column was not created today, it was created weeks ago.
Is there any configuration the vendor could have put in place that would disable the auto assignment of the seed value and force the developer to "fetch" the next seed value manually?
SQL Server stores the seed/nextID value to be used. I'm wondering if the conversion from Oracle neglected to set that value. Try using the the following command on that table to check what it's seed value is:
DBCC CHECKIDENT ( table_name, NORESEED )
Maybe it actually is null, which is causing the error. Then you can use a variation of the same command to 'reseed' or set the next value to be used.
For more information and options:
http://msdn.microsoft.com/en-us/library/ms176057(v=sql.110).aspx
This is a pretty old question, but I was lead here when one of my developers had this very issue and wanted to share what caused/fixed it for us.
Basically, on another tab in SQL server "Edit Top 200 Rows" was open for the specified table.
Once this tab was closed, the insert worked without issue.
Hope this helps someone!

SQL Server 2008 - Identity Column Skipped a Row ID

I have never seen this before, the rows will be sequential but I have noticed that it skipped over a particular "ID".... 1 2 3 4 6 7 8... missing 5...
There are no transactions in the INSERT stored procedure so nothing to roll back
We do not allow the deletion of records.
What else can be the case?
Probably a failed insert due to some other unique constraint on the table or a foreign key reference in the table and you try to insert an invalid fk value.
The insert doesn't have to be in a transaction.
The identity value increments even on a failed insert.
Igor mentions an important point about identities and transactions. From the docs:
Failed statements and transactions can
change the current identity for a
table and create gaps in the identity
column values. The identity value is
never rolled back even though the
transaction that tried to insert the
value into the table is not committed.
For example, if an INSERT statement
fails because of an IGNORE_DUP_KEY
violation, the current identity value
for the table is still incremented.
Any way, identity counter does not restore your value (if you have executed with transaction or without it). The same behavior has oracle (sequences).
Identity is not transactional.
You may use your own primary key counter and control access to it.
Failed attempts generates an identity value even though it is not inserted into the data table. Then, this results to the lost of an identity (it's a shame I can no longer find the post where I have learned it!).

What could cause an IDENTITY column to become corrupted?

I had an unusual problem yesterday where I was suddenly unable to insert records into a table with an identity column.
A simple insert like this: INSERT INTO MyTable (Column1, Column2) VALUES ('text', 236764)
Started throwing a primary key constraint violation.
I ran DBCC CHECKIDENT on the table, and realized that SQL Server had stopped updating the last used value, so that when it was inserting it was incrementing using the old value and the new identity value usually already existed in the table, hence the violation errors.
Resolving the problem wasn't an issue, I just reseeded the table for the next highest sequence number, but I've never seen this happen before!
Does anyone have any idea what might cause SQL Server to stop updating identity properties, and where I might look for evidence? There is no replication or any triggers involved, it's just a plain old table.
EDIT: SQL Log Rescue would have been ideal, but it only works on SQL Server 2000. Is there a similar tool out there for SQL 2005 logs?
If someone has inserted to the table using SET IDENTITY_INSERT ON, someone could absolutely have entered in an invalid value for the table. That would be my first guess. You could use a log analyzer like SQL Log Rescue to go back in time through the transaction logs and see if you could find who the bad person was who messed up your data...
I think SET IDENTITY_INSERT ON reseeds the Identity.
From BOL
If the value inserted is larger than
the current identity value for the
table, SQL Server automatically uses
the new inserted value as the current
identity value.
The only way I could reproduce this issue was to manually set the seed too low with DBCC CHECKIDENT.