Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-34652

Deadlock when upgrading shared lock to exclusive

Details

    Description

      Let's have a look on the following scenario:

      Tables init script:

      create table ParentTable
      (
          id  bigint auto_increment primary key,
          uid varchar(50) not null
      );
       
       create table ChildTable
      (
          id             bigint auto_increment primary key,
          uid            varchar(50) not null,
          parentTable_id bigint not null,
          constraint FK_ChildTable_To_ParentTable foreign key (parentTable_id) references ParentTable (id)
      );
       
      create index IDX_ParentTable_UID on ParentTable (uid);
      create index IDX_ChildTable_UID on ChildTable (uid);
       
      INSERT INTO ParentTable(uid) VALUES('a');
       
      INSERT INTO ChildTable(uid, parentTable_id) VALUES('a', 1);
      INSERT INTO ChildTable(uid, parentTable_id) VALUES('b', 1);
      

      Bug reproduction scenario:

      Transaction #1:

      SET autocommit=0;
      START TRANSACTION;
      insert into ChildTable(uid, parentTable_id) VALUES('c', 1);
      

      Transaction #2:

      SET autocommit=0;
      START TRANSACTION;
      update ParentTable set uid='tran-2' where id = 1;
      

      here transaction #2 waits as T#1 issued shared lock on ParentTable when insert to ChildTable was made (with the use of foreign key)

      Now, issuing and update to ParentTable on Transaction #1:

      UPDATE ParentTable SET uid = 'tran-1' WHERE id = 1;
      

      results in a deadlock on T#2 connection:

      Error Code: 1213. Deadlock found when trying to get lock; try restarting transaction
      

      show engine innodb status:

       
       =====================================
       2024-07-26 11:52:53 0x7f4b8c060640 INNODB MONITOR OUTPUT
       =====================================
       Per second averages calculated from the last 0 seconds
       -----------------
       BACKGROUND THREAD
       -----------------
       srv_master_thread loops: 0 srv_active, 15401 srv_idle
       srv_master_thread log flush and writes: 15391
       ----------
       SEMAPHORES
       ----------
       ------------------------
       LATEST DETECTED DEADLOCK
       ------------------------
       2024-07-26 11:52:45 0x7f4b8c0f6640
       *** (1) TRANSACTION:
       TRANSACTION 136, ACTIVE 31 sec starting index read
       mysql tables in use 1, locked 1
       LOCK WAIT 5 lock struct(s), heap size 1128, 2 row lock(s), undo log entries 1
       MariaDB thread id 4, OS thread handle 139962449094208, query id 251 192.168.14.89 root Updating
       UPDATE ParentTable SET uid = 'tran-1' WHERE id = 1
       *** WAITING FOR THIS LOCK TO BE GRANTED:
       RECORD LOCKS space id 8 page no 3 n bits 8 index PRIMARY of table `prusi`.`ParentTable` trx id 136 lock_mode X locks rec but not gap waiting
       Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
        0: len 8; hex 8000000000000001; asc         ;;
        1: len 6; hex 000000000000; asc       ;;
        2: len 7; hex 80000000000000; asc        ;;
        3: len 6; hex 7472616e2d31; asc tran-1;;
       
       *** CONFLICTING WITH:
       RECORD LOCKS space id 8 page no 3 n bits 8 index PRIMARY of table `prusi`.`ParentTable` trx id 136 lock mode S locks rec but not gap
       Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
        0: len 8; hex 8000000000000001; asc         ;;
        1: len 6; hex 000000000000; asc       ;;
        2: len 7; hex 80000000000000; asc        ;;
        3: len 6; hex 7472616e2d31; asc tran-1;;
       
       
       *** (2) TRANSACTION:
       TRANSACTION 137, ACTIVE 12 sec starting index read
       mysql tables in use 1, locked 1
       LOCK WAIT 2 lock struct(s), heap size 1128, 1 row lock(s)
       MariaDB thread id 6, OS thread handle 139962448479808, query id 249 192.168.14.89 root Updating
       update ParentTable
       set uid='tran-2'
       where id = 1
       *** WAITING FOR THIS LOCK TO BE GRANTED:
       RECORD LOCKS space id 8 page no 3 n bits 8 index PRIMARY of table `prusi`.`ParentTable` trx id 137 lock_mode X locks rec but not gap waiting
       Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
        0: len 8; hex 8000000000000001; asc         ;;
        1: len 6; hex 000000000000; asc       ;;
        2: len 7; hex 80000000000000; asc        ;;
        3: len 6; hex 7472616e2d31; asc tran-1;;
       
       *** CONFLICTING WITH:
       RECORD LOCKS space id 8 page no 3 n bits 8 index PRIMARY of table `prusi`.`ParentTable` trx id 136 lock mode S locks rec but not gap
       Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 0
        0: len 8; hex 8000000000000001; asc         ;;
        1: len 6; hex 000000000000; asc       ;;
        2: len 7; hex 80000000000000; asc        ;;
        3: len 6; hex 7472616e2d31; asc tran-1;;
       
       *** WE ROLL BACK TRANSACTION (1)
       ------------
       TRANSACTIONS
       ------------
       Trx id counter 138
       Purge done for trx's n:o < 136 undo n:o < 0 state: running but idle
       History list length 0
       LIST OF TRANSACTIONS FOR EACH SESSION:
       ---TRANSACTION (0x7f4b8c9df680), not started
       0 lock struct(s), heap size 1128, 0 row lock(s)
       ---TRANSACTION 136, ACTIVE 39 sec
       5 lock struct(s), heap size 1128, 2 row lock(s), undo log entries 1
       MariaDB thread id 4, OS thread handle 139962449094208, query id 251 192.168.14.89 root 
       --------
       FILE I/O
       --------
       Pending flushes (fsync): 0
       188 OS file reads, 17 OS file writes, 18 OS fsyncs
       0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
       ---
       LOG
       ---
       Log sequence number 132359
       Log flushed up to   132359
       Pages flushed up to 110251
       Last checkpoint at  110235
       ----------------------
       BUFFER POOL AND MEMORY
       ----------------------
       Total large memory allocated 167772160
       Dictionary memory allocated 857160
       Buffer pool size   8064
       Free buffers       7759
       Database pages     305
       Old database pages 0
       Modified db pages  27
       Percent of dirty pages(LRU & free pages): 0.335
       Max dirty pages percent: 90.000
       Pending reads 0
       Pending writes: LRU 0, flush list 0
       Pages made young 0, not young 0
       0.00 youngs/s, 0.00 non-youngs/s
       Pages read 167, created 138, written 0
       0.00 reads/s, 0.00 creates/s, 0.00 writes/s
       No buffer pool page gets since the last printout
       Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
       LRU len: 305, unzip_LRU len: 0
       I/O sum[0]:cur[0], unzip sum[0]:cur[0]
       --------------
       ROW OPERATIONS
       --------------
       0 read views open inside InnoDB
       state: sleeping
       ----------------------------
       END OF INNODB MONITOR OUTPUT
       ============================
       
      

      Expected behaviour would be for MariaDBSever to allow T#1 to perform update and then allow T#2 to execute normally, without a deadlock.

      It seems like the same as here: https://bugs.mysql.com/bug.php?id=48652 (reported many years ago for previous version of MySQL Server). On other DB providers (MS SQL Server or even POSTGRESQL) in such scenario there is no deadlock.

      Attachments

        Issue Links

          Activity

            People

              vlad.lesin Vladislav Lesin
              mprusinski Marcin Prusinski
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.