I have a Microsoft SQl server 2005 database with a table whose primary key has the identity specification is set to yes to auto increment.
Recently the primary key skipped two numbers(which I understand is normal as they are not necessarily sequential).
However I would like to find out, if possible, why they skipped and when, i.e. if a stored procedure rollback occured and the primary key sequence didn't rollback or they were deleted somehow.
My question is, does Microsoft SQL server management studio have a designated area that stored records such as this, i.e. transaction logs etc for me to have a look at to try and determine why this skip happened.
Assuming you have an IDENTITY that increments by 1 each time, then you will see haps in your ids if a ROLLBACK occurs - in the event of a rollback, the IDENTITY value will not be reverted back so the ID value it assigned for that operation will essentially be lost. This is entirely normal behaviour.
Suppose you have a high volume of INSERTs, in the event of one insert failing/rolling back, then rolling back the IDENTITY value increment would be a nightmare as there could have been a whole swathe of INSERTs in the mean time.
Unless your code log it there is no record. So no: SQL Server does not take note of this.
A transaction rollback or an INSERT error (which is a single statement rollback) will generate gaps in the number sequence. SQL Server does not take note of this.
Related
Oracle 10g -- due to a compatibility issue with a 9i database, I'm pulling data through a 10g database (to be used by an 11g database) using INSERT INTO...SELECT statements via a scheduled job that runs every 15 minutes. I notice that TRUNCATE statements are much faster than DELETE statements and have read that a 'downside' to DELETE statements is that they never decrease the table high-water mark. My use for this data is purely read-only -- UPDATEs and INSERTs are never issued against the tables in question.
Given the above, I want to avoid the possible situation where my 'working' database (Oracle 11g) attempts to read from a table on my staging database (10g) that is empty for a period of time because the TRUNCATE happened straight away and the INSERT INTO...SELECT from the 9i database is taking a couple of minutes to complete.
So, I'm wondering if that is how Oracle handles TRUNCATEs within a transaction, or if the whole operation is performed and COMMITted, despite the fact that TRUNCATEs can't be rolled back? Or, put another way, from an external SELECT point of view, if I wrap a TRUNCANTE and INSERT INTO...SELECT on a table in a transaction, will the table ever appear empty to an external SELECT reading from the table?
Once a table has been truncated in a transaction, you cannot do anything else with that table in the same transaction; you have to commit (or rollback) the transaction before you can use that table again. Or, it may be that truncating a table effectively terminates the current transaction. Either way, if you use TRUNCATE, you have a window when the table is truncated (empty) but the INSERT operation has not completed. This is not what you wanted, but it is what Oracle provides.
You can do partition exchange. Have 2 partitions in staging table; p_OLD and p_NEW.
Before insert do partition exchange "new"->"old" and truncate "new" partition. (At this point if you select from table you see old data)
Insert data into "new" partition, truncate "old" partition. (At this point you see new data).
With this approach your table is never empty to the onlooker.
Why do you need 3 Oracle environments?
I am using SQL CDC to track changes for multiple tables in SQL Server. I would want to report out these changes in right sequence for each I have a program which collects the data from each CDC table. But I want to make sure that all the changes that are happening to these tables are reported in correct sequence. Can I rely on LSN for the right sequence?
The LSN number is unique for a given transaction but is not globally unique. If you have multiple records within the same transaction they will all share the same __$start_lsn value in cdc. If you want the correct order of operations you need to sort by __$start_lsn, __$seqval, then __$operation. The __$seqval represents the id of the individual operation within the wrapping transaction.
For example, I have a table in the dbo schema named foo. It has one column y. If I run this statement:
INSERT INTO dbo.foo VALUES (1);
INSERT INTO dbo.foo VALUES (2);
Then I will see two separate LSN values in cdc because these are in two separate transactions. If I run this:
BEGIN TRAN
INSERT INTO dbo.foo VALUES (1);
INSERT INTO dbo.foo VALUES (2);
COMMIT TRAN
Then I will see one LSN value for both records, but they will have different __$seqval values, and the seqval for my first record will be less than the seqval for my second record.
LSN is unique, ever increasing within the database, across all tables in that database.
In most cases LSN value is unique across all tables, however I found instances where one single LSN value belongs to the changes in 40 tables. I don't know the SQL script that associated with those changes, but I know that all operations were 'INSERT'.
Not sure if it is a bug. CDC documentations is poor, covers just basics. Not many users know that CDC capture process has many bugs confirmed by MS for both SQL 2014 & 2016 (we have the open case).
So I would not rely on the documentation. It may be wrong in some scenarios. It's better to implement more checks and test it with large volume of different combinations of changes.
I also encountered that scenario. In my experience and what I understood is in your first example, there are 2 transactions happened so you will really get 2 different LSN. While in your second example, you only have 1 transaction with 2 queries inside. The CDC will count it as only 1 transaction since it is inside BEGIN and END TRAN. I can't provide links to you since this is my personal experience.
When I try to insert a new row in the table, if there is any exception occurs in this transaction then data is rollback.
Now when a new entry is succesfully inserted next time, AutoIncrement id is updated with next value. Means there is Gap between two consequetive Unique Id in the table.
Is there any valid way to overcome this problem?
Thanks in advance
The answer has to be said - no.
The whole idea of IDENTITY columns is to not be meaningful, and to be transaction agnostic - so that the numbers can be dished out without care of other transactions rolling back or not. Imagine a 1000 insert per second system being held up for 10ms for each transaction (insert) to decide whether it will commit! (fyi 10ms * 100 = 1s)
Note: In SQL Server 2012 (latest SP/patch level at time of writing), there is a "feature" noted here on Connect related to identities.
Also even prior to 2012, you don't even need to rollback to consume an IDENTITY value - see here https://stackoverflow.com/a/16156419/573261
This applies to other major RDBMS as well for the same reasons, e.g.
PostgreSQL sequences
Important: To avoid blocking concurrent transactions that obtain numbers from the same sequence, a nextval operation is never rolled back; that is, once a value has been fetched it is considered used, even if the transaction that did the nextval later aborts. This means that aborted transactions might leave unused "holes" in the sequence of assigned values.
(emphasis mine)
In SQL Server, if a transaction involving the inserting of a new row gets rolled back, a number is skipped in the identity field.
For example, if the highest ID in the Foos table is 99, then we try to insert a new Foo record but roll back, then ID 100 gets 'used up' and the next Foo row will be numbered 101.
Is there any way this behaviour can be changed so that identity fields are guaranteed to be sequential?
What you are after will never work with identity columns.
They are designed to "give out" and forget, by-design so that they don't cause waits or deadlocks etc. The property allows IDENTITY columns to be used as a sequence within a highly transactional system with no delay or bottlenecks.
To make sure that there are no gaps means that there is NO WAY to implement a 100-insert per second system because there would be a very long queue to figure out if the 1st insert was going to be rolled back.
For the same reason, you normally do not want this behaviour, nor such a number sequence for a high volume table. However, for very infrequent, single-process tables (such as invoice number by a single process monthly), it is acceptable to put a transaction around a MAX(number)+1 or similar query, e.g.
declare #next int
update sequence_for_tbl set #next=next=next+1
.. use #next
SQL Identity (autonumber) is Incremented Even with a Transaction Rollback
Question title is the crux of the problem. I have an Access 2007 (2003 format) front-end with a SQL Server 2008 Express back-end. The input form has a subform linked to another table. When adding a record in the main form, the PK field of the table (set to auto increment) is skipping about four IDs (I say about because sometimes it's three, sometimes five, sometimes 4).
To illustrate, if the last ID is 1234, the ID of the new record might be 1238.
I've stepped through the code, but haven't found anything that would indicate multiple saves or deletes. This problem manifests regardless of whether any records are added to the subform.
I realize this could be anything, but I'm hoping someone might have some insight or suggestions of avenues to investigate.
It could be that some INSERTs in the table are being done within a transaction and the transaction is then rolled back - this would use up IDs, leaving gaps.
Check the Identity specification on the database to see what the Identity Increment is. It may be incrementing at an interval greater than 1, though that wouldn't explain your odd numbering. It's a good starting point.
Also, you could be having people start a record and then deleting it ala the transactions being rolled back and the incrementer being increased.
fire up sql profiler and observer the RPC:Completed and SqlStmt:Completed events to see what exactly is getting executed.
SQL Server doesn't just skip numbers for no reason. it looks like it's inserting something and rolling it back or inserting rows fail.