Details
-
Bug
-
Status: Closed (View Workflow)
-
Critical
-
Resolution: Not a Bug
-
10.5.12, 10.11.10
-
Operating System: RHEL
InnoDB Storage Engine enabled.
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
- relates to
-
MDEV-35957 Defer Foreign key constraint check
-
- Open
-