Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding concurrency problems with MAX+1 integer in SQL Server 2008... making own IDENTITY value

Tags:

I need to increment an integer in a SQL Server 2008 column.

Sounds like I should use an IDENTITY column, but I need to increment separate counters for each of my customers. Think of an e-commerce site where each customer gets their own incrementing order number, starting with 1. The values must be unique (per customer).

For example,

Customer1  (Order #s 1,2,3,4,5...) Customer2  (Order #s 1,2,3,4,5...) 

Essentially, I will need to manually do the work of SQL's identity function since the number of customers is unlimited and I need order # counters for each of them.

I am quite comfortable doing:

BEGIN TRANSACTION   SELECT @NewOrderNumber = MAX(OrderNumber)+1 From Orders where CustomerID=@ID   INSERT INTO ORDERS VALUES (@NewOrderNumber, other order columns here) COMMIT TRANSACTION 

My problem is locking and concurrency concerns and assuring a unique value. It seems we need to lock with TABLOCKX. But this is a high volume database and I can't just lock the whole Orders table every time I need to do a SELECT MAX+1 process and insert a new order record.

But, if I don't lock the whole table, then I might not get a unique value for that customer. Because some of our order entry is done after-the-fact in batches by a multi-threaded Windows process, it is possible that 2 operations will be simultaneously wanting to insert a new order for the same customer.

So what locking methodology or technique will avoid deadlocks and still let me maintain unique incrementing order numbers PER customer?

like image 893
stackonfire Avatar asked Jan 21 '12 19:01

stackonfire


People also ask

What happens when identity column reaches max?

Each time a row is inserted into the table, the identity column is assigned the next highest value. If the identity reaches the maximum value, inserts will fail.

Why does SQL identity jump 1000?

In SQL Server 2012 - MS had introduced 'Identity Cache'. This feature had a bug of auto-incrementing ID column by '1000'. For example, if ID columns are 1, 2 and when an ID Jump happens the next ID column is 1003, instead of '3'. There are workarounds available to fix this issue.


1 Answers

In SQL Server 2005 and later, this is best done atomically, without using any transactions or locking:

update ORDERS  set OrderNumber=OrderNumber+1  output inserted.OrderNumber where CustomerID=@ID 
like image 91
J.T. Taylor Avatar answered Oct 14 '22 19:10

J.T. Taylor