dolt icon indicating copy to clipboard operation
dolt copied to clipboard

Race condition in AutoIncrementTracker can cause two transactions to get assigned the same auto-incrementing ID.

Open nicktobey opened this issue 1 year ago • 0 comments

AUTO INCREMENT is supposed to be unaffected by transactions: not-yet-committed transactions can still advance the counter, and rolling back a transaction does not reset the counter. This allows two concurrent transactions to both insert into the same table with an AUTO INCREMENT column without causing a transaction conflict.

Unfortunately, it appears that in rare cases we can generate the same ID for two concurrent transactions, causing a conflict for whichever transaction commits second.

I was only able to get this to reproduce when the insertion was happening as the result of a trigger.

Steps to reproduce:

dolt sql <<SQL
CREATE TABLE test1 (
  pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,
  c0 int,
  index t1_c_index (c0)
);
CREATE TABLE test2 (
  pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,
  c0 int,
  index t2_c_index (c0)
);
CREATE TABLE timestamps (
  pk int NOT NULL PRIMARY KEY AUTO_INCREMENT,
  t int
);

delimiter |
CREATE TRIGGER t1 AFTER INSERT ON test1
  FOR EACH ROW
  BEGIN
    INSERT INTO timestamps VALUES (0, 1);
  END|

CREATE TRIGGER t2 AFTER INSERT ON test2
  FOR EACH ROW
  BEGIN
    INSERT INTO timestamps VALUES (0, 2);
  END|
delimiter ;

CREATE VIEW bin AS SELECT 0 AS v UNION ALL SELECT 1;
CREATE VIEW sequence5bit AS SELECT b1.v + 2*b2.v + 4*b3.v + 8*b4.v + 16*b5.v AS v from bin b1, bin b2, bin b3, bin b4, bin b5;
CREATE VIEW sequence10bit AS SELECT b1.v + 32*b2.v AS v from sequence5bit b1, sequence5bit b2;
SQL

dolt sql-server &
server_pid = $!
dolt sql -q "INSERT INTO test1 (c0) select v from sequence10bit; SELECT * from timestamps; COMMIT;" &
dolt sql -q "INSERT INTO test2 (c0) select v from sequence10bit; SELECT * from timestamps; COMMIT;"
wait $!
kill $server_pid

There is a high likelihood that one of the transactions will fail. By comparing both transactions versions of the timestamps table, we can see that a small fraction of the primary keys appear in both tables. (Out of the 2048 inserts that this script makes, there are usually anywhere in the range of 1-7 duplicates.)

nicktobey avatar Apr 05 '24 22:04 nicktobey