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

Deadlock Issue with Foreign Key Constraints on concurrent execution

    XMLWordPrintable

Details

    Description

      Problem Summary:
      We are experiencing a deadlock issue in MariaDB when executing concurrent INSERT and UPDATE operations on two tables. TO give you a sample of what we are doing. Assume having two tables (PRODUCT and PRODUCT_LEDGER) that are related via a foreign key. The problem occurs when two different sessions are running the same stored procedure concurrently, which inserts data into PRODUCT_LEDGER and updates a PRODUCT record. Despite the operations being logically ordered, MariaDB detects a deadlock and rolls back one of the transactions.

      Details of the Tables and Procedure:
      Tables:
      CREATE TABLE `PRODUCT` (
      `PRODUCT_NUM` VARCHAR(35) NOT NULL COLLATE 'latin1_general_ci',
      `PRODUCT_NAME` VARCHAR(128) NULL COLLATE 'latin1_general_ci',
      `BALANCE_DUE` DECIMAL(20,2) NULL,
      PRIMARY KEY (`PRODUCT_NUM`)
      )
      COLLATE='latin1_general_ci'
      ENGINE=InnoDB;

      CREATE TABLE `PRODUCT_LEDGER` (
      `PRODUCT_LEDGER_NUM` VARCHAR(35) NOT NULL COLLATE 'latin1_general_ci',
      `PAY_TO_PRODUCT_NUM` VARCHAR(35) NULL COLLATE 'latin1_general_ci',
      PRIMARY KEY (`PRODUCT_LEDGER_NUM`),
      INDEX `fk_ple_pay_to_product` (`PAY_TO_PRODUCT_NUM`),
      CONSTRAINT `fk_ple_pay_to_product` FOREIGN KEY (`PAY_TO_PRODUCT_NUM`) REFERENCES `PRODUCT` (`PRODUCT_NUM`) ON UPDATE RESTRICT ON DELETE RESTRICT
      )
      COLLATE='latin1_general_ci'
      ENGINE=InnoDB;

      Stored Procedure:
      DELIMITER //

      CREATE DEFINER=`root`@`%` PROCEDURE `TestDeadlock`(
      IN `vEntryNum` VARCHAR(30)
      )
      LANGUAGE SQL
      NOT DETERMINISTIC
      CONTAINS SQL
      SQL SECURITY DEFINER
      COMMENT ''
      BEGIN
      DECLARE done INT DEFAULT FALSE;
      DECLARE i INT DEFAULT 0;

      DECLARE exit handler FOR sqlexception
      BEGIN
      GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
      SELECT @text, @errno;
      ROLLBACK;
      END;

      START TRANSACTION;

      INSERT INTO product_ledger(PRODUCT_LEDGER_NUM, PAY_TO_PRODUCT_NUM)
      VALUES (vEntryNum, '2020');

      SELECT SLEEP(5);

      UPDATE product SET BALANCE_DUE = BALANCE_DUE + 100 WHERE PRODUCT_NUM = '2020';

      COMMIT;
      END //
      DELIMITER ;

      Steps to Reproduce:
      Execute TestDeadlock('234235') in Session 1.
      Execute TestDeadlock('546674') in Session 2 concurrently.
      Both sessions will run the procedure and attempt to insert into PRODUCT_LEDGER and update PRODUCT.
      Deadlock occurs, and MariaDB rolls back one of the transactions.

      Observations:
      The deadlock occurs despite the logical order of the operations.
      Both sessions seem to be waiting for each other on the same row in the PRODUCT table, but MariaDB detects a deadlock and chooses to roll back one transaction instead of waiting.
      The issue appears to be related to InnoDB's row-level locking and foreign key constraints.

      Questions:
      Why does MariaDB not simply wait for the lock instead of detecting a deadlock?
      Are there any specific configurations or best practices to avoid deadlocks in this scenario without changing the query logic?

      MariaDB Version:
      MariaDB 10.5.12, 10.11

      Attachments

        Issue Links

          Activity

            People

              marko Marko Mäkelä
              jaswanth Jaswanth
              Votes:
              0 Vote for this issue
              Watchers:
              4 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.