I suffer a strange mysql deadlock recently, my tables look like(for simplicity I deleted unrelevant columns):
CREATE TABLE Node (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`nodeId` varchar(128) NOT NULL UNIQUE,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE JobQueue (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`workerManagementNodeId` varchar(32) DEFAULT NULL,
CONSTRAINT `fkJbqMgmtNodeId` FOREIGN KEY (`workerManagementNodeId`) REFERENCES `Node` (`nodeId`) ON DELETE SET NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
when my node goes down, it will delete record in Node table. At this point, job queue may be in process of deleting a queue in JobQueue table which has a foreign key to Node.nodeId. Then mysql throws out an exception:
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
I checked the database, JobQueue was successfully deleted but Node wasn't. I understand order of foreign key may cause deadlock, but in my case Node table has no foreign key only primary key. Then how can the deadlock happen?
BTW: I am pretty sure the deadlock is caused by JobQueue, I spent much time narrowing down this problem so in my test only these two tables will be used.
UPDATE:
CREATE TABLE JobQueueEntry (
`id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`jobQueueId` bigint unsigned NOT NULL,
`issuerManagementNodeId` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fkJbqEtryMgmtNodeId` FOREIGN KEY (`issuerManagementNodeId`) REFERENCES `Node` (`nodeId`) ON DELETE SET NULL,
CONSTRAINT `fkJobQueueId` FOREIGN KEY (`jobQueueId`) REFERENCES `JobQueue` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
I finally notice it's still an issue caused by foreign key order. there is actually another table JobQueueEntry which has both foreign key to Node and JobQueue in reversed order. so when deleting a node it's trying to update JobQueue and JobQueueEntry. the deadlock happens because JobQueueEntry has foreign key to JobQueue before node.
thanks @ctrl's answer!