Dear colleagues,
I use SQL Server 2019, Standard Edition.
Our table with journal entries has a strictly increasing PK field. Nothing weird there.
With strictly increasing I mean that even when a rollback happens, the next insert will not cause a gap.
We have a table with one record containing the last used number. Every transaction posting a journal entry does the following.
- Start a transaction
- Lock the table with the last used number (always the first action to prevent deadlocks on this table)
- Get the number, increment it and post the new number
- Do the rest
- Commit or Rollback (when a rollback is issued, also the increment is rolled back)
This works, but when a long running transaction creates journal entries, this causes awful performance degradation (for obvious reasons). I cannot use an identity column because the journal entries are stored in several tables sharing the same PK. I want to use a sequence to prevent the problems we have now. However, even if the sequence doesn't cache values, we still can have gaps in the numbering in case of a rollback. The accountants do not like this.
My question:
Is there a way to add a new column that I can populate with a strictly increasing number that is assigned after transactions are committed? As far as I know, there is no way I can receive a notification when a transaction is committed. I do not find it a problem if the new column doesn't have the same order as the PK. This might happen in the following scenario.
- Last used PK = x, last used stricly increasing number = y
- Transaction A starts and gets PK = x+1
- Transaction B starts and gets PK = x+2
- Transaction C starts and gets PK = x+3
- Transaction C commits and gets PK = x+3, Increasing number = y+1
- Transaction B rolls back
- Transaction A commits and gets PK = x+1, Increasing number = y+2
(gap between x+1 and x+3, increasing number in different order)
Ah, just found a counter example. If the insert in the journal table isn't the last thing to happen in a proc, SQL following the insert in the journal table might fail, causing a sequence number to be lost. I think I will go with the numbering using a job.
The order of the numbering doesn't have to be the order of committing. As long as I have a strictly ascending number, the accountants are satisfied. I will order on the PK, for which I am going to use a sequence. In that case the new number mostly has the order as the old PK. The only exception is that when old PK x and x+2 have committed records while the process that received x + 1 is still busy just at the moment that my numbering job fires. That's ok with me.