The following 2 queries enounter DB deadlock in my program:
DELETE FROM proxies
WHERE NOT EXISTS (
SELECT 1 FROM proxy_xref_proxy_list AS pxpl
WHERE pxpl.ProxyID=proxies.ID
AND (pxpl.DeactivationTS IS NULL OR pxpl.DeactivationTS >= (NOW() - INTERVAL 24 HOUR))
ORDER BY pxpl.ProxyListID
LIMIT 1
)
ORDER BY proxies.ID
INSERT IGNORE INTO proxy_xref_proxy_list (ProxyID, ProxyListID)
(SELECT ID, 13 FROM proxies
JOIN new_proxies ON proxies.Url=new_proxies.Url
ORDER BY proxies.ID)
ON DUPLICATE KEY UPDATE DeactivationTS=NULL
However, they are both ordered by proxies.ID
. Why do they deadlock and how to solve this?
Tables:
CREATE TABLE `proxies` (
`ID` BIGINT(20) NOT NULL AUTO_INCREMENT,
`Url` VARCHAR(767) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
`Schema` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`Host` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`Port` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`SuccessCount` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`UnknownCount` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
`FailureCount` BIGINT(20) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`) USING BTREE,
UNIQUE INDEX `UrlUnique` (`Url`) USING BTREE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
CREATE TABLE `proxy_xref_proxy_list` (
`ProxyID` BIGINT(20) NOT NULL,
`ProxyListID` BIGINT(20) NOT NULL,
`DeactivationTS` DATETIME NULL DEFAULT NULL,
PRIMARY KEY (`ProxyID`, `ProxyListID`) USING BTREE,
UNIQUE INDEX `DisactivationTS_ProxyID_ProxyListID` (`DeactivationTS`, `ProxyID`, `ProxyListID`) USING BTREE,
INDEX `ProxyXRefProxyList_ProxyListID_FK2` (`ProxyListID`, `DeactivationTS`) USING BTREE,
CONSTRAINT `ProxyXRefProxyList_ProxyID_FK1` FOREIGN KEY (`ProxyID`) REFERENCES `mydb`.`proxies` (`ID`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `ProxyXRefProxyList_ProxyListID_FK2` FOREIGN KEY (`ProxyListID`) REFERENCES `mydb`.`proxy_lists` (`ID`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
CREATE TEMPORARY TABLE `new_proxies` (
`Url` VARCHAR(767) NOT NULL DEFAULT '' COLLATE 'utf8mb4_unicode_ci',
`Schema` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`Host` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
`Port` TINYTEXT NULL DEFAULT NULL COLLATE 'utf8mb4_unicode_ci',
UNIQUE INDEX `UrlUnique` (`Url`) USING BTREE
)
COLLATE='utf8mb4_unicode_ci'
ENGINE=InnoDB
;
Table proxy_lists
referenced by the foreign key is linked to proxies
via a many-to-many relation.
UPDATE1: Upon the request of @Rick James, here is a query that selects the proxy IDs that need deletion:
SELECT p.ID FROM proxies AS p
LEFT JOIN proxy_xref_proxy_list AS pxpl
ON p.ID=pxpl.ProxyID
AND (pxpl.DeactivationTS IS NULL OR pxpl.DeactivationTS >= (NOW() - INTERVAL 24 HOUR))
WHERE pxpl.ProxyID IS NULL