Hekaton – Classic deadlock scenario

Ever since CTP2 was released a few weeks back, I have become interested in the new In-Memory OLTP (aka Hekaton) feature currently being constructed for SQL Server 2014.  Once I learned that Hekaton uses lock-free structures, one of the first things I started to wonder about is how Hekaton handles a classic deadlock scenario.  After downloading and installing the CTP, I created a Hekaton-enabled database and then added a couple of tables:

create table CheckingAccount
(
       OwnerId int not null primary key nonclustered hash with (bucket_count = 1000),
       Balance money
) with (memory_optimized = on, durability = schema_and_data);
 
create table SavingsAccount
(
       OwnerId int not null primary key nonclustered hash with (bucket_count = 1000),
       Balance money
) with (memory_optimized = on, durability = schema_and_data);
 
insert CheckingAccount (OwnerId, Balance) values (123, 1000.00);
insert SavingsAccount (OwnerId, Balance) values (123, 2000.00);

Now in connection 1, I run the following:

begin transaction
 
update SavingsAccount with (snapshot)
set           Balance -= 300.00
where  OwnerId = 123;

In connection 2:

begin transaction
 
update CheckingAccount with (snapshot)
set           Balance -= 200.00
where  OwnerId = 123;

Back in connection 1:

update CheckingAccount with (snapshot)
set           Balance += 300.00
where  OwnerId = 123;

Msg 41302, Level 16, State 110, Line 1
The current transaction attempted to update a record that has been updated since this transaction started. The transaction was aborted.
Msg 3998, Level 16, State 1, Line 1
Uncommittable transaction is detected at the end of the batch. The transaction is rolled back.
The statement has been terminated.

So right there we have the answer to how Hekaton handles this scenario: the second attempt at an update on the same row causes the transaction to fail.

Completing the scenario, switch back to connection 2 and run:

update SavingsAccount with (snapshot)
set           Balance += 200.00
where  OwnerId = 123;
 
commit transaction

Now check the state of the tables:

select ca.OwnerId, ca.Balance CheckingBalance, sa.Balance SavingsBalance
from CheckingAccount ca inner join SavingsAccount sa
on ca.OwnerId = sa.OwnerId where ca.OwnerId = 123;

hekaton-consistency
So the tables are transactionally consistent. Bear in mind that in the classic version of this scenario (using disk-based tables), connection 2 would have been chose as the deadlock victim. It’s OK that in this world the opposite is the case because the rules of consistency don’t dictate who is the “winner” and who is the “loser,” only that end result “balances out.”

Leave a Reply

Your email address will not be published. Required fields are marked *