mysql中的死锁可能是由触发器引起的

问题描述

我对MysqL中的死锁有疑问。 有一个s_report表记录数据,有sql

CREATE TABLE `s_report`  (
  `report_id` varchar(32) CHaraCTER SET utf8 COLLATE utf8_general_ci NOT NULL,`user_id` varchar(128) CHaraCTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,`case_tracking_status` varchar(32) CHaraCTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,PRIMARY KEY (`report_id`) USING BTREE,INDEX `id_userid`(`user_id`) USING BTREE
) ENGINE = InnoDB CHaraCTER SET = utf8 COLLATE = utf8_general_ci  

,我在s_report表上有两个触发器。 触发器定义:

DROP TRIGGER IF EXISTS `s_report_record_on_insert`;
delimiter ;;
CREATE TRIGGER `s_report_on_insert` AFTER INSERT ON `s_report` FOR EACH ROW BEGIN
        INSERT INTO s_report_back_up (
            `report_id`,`user_id`,`case_tracking_status`,)
    VALUES
        (
            new.report_id,new.user_id,new.case_tracking_status
        );
END
;;
delimiter ;
DROP TRIGGER IF EXISTS `s_report_on_update`;
delimiter ;;
CREATE TRIGGER `s_report_on_update` AFTER UPDATE ON `s_report` FOR EACH ROW BEGIN
    DECLARE report_exist INT DEFAULT 0;
    
    SET report_exist = ( SELECT count( * ) FROM s_report_back_up WHERE report_id = new.report_id );
    IF report_exist > 0 THEN
            UPDATE `s_reportback_up` 
            SET 
            `user_id` = new.user_id,`case_tracking_status` = new.case_tracking_status,WHERE
            report_id = new.report_id;
        ELSE 
        INSERT INTO s_report_back_up (
            `report_id`,)
        VALUES
            (
                new.report_id,new.case_tracking_status
            );
        
    END IF;
END
;;
delimiter ;

您可以看到,有一个s_report_back_up表,我使用触发器来备份数据。 有s_report_back_up表sql

CREATE TABLE `s_report_back_up`  (
  `id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,`report_id` varchar(32) CHaraCTER SET utf8 COLLATE utf8_general_ci NOT NULL,PRIMARY KEY (`id`) USING BTREE,INDEX `index_userid`(`user_id`) USING BTREE,INDEX `index_report_id`(`report_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 630 CHaraCTER SET = utf8 COLLATE = utf8_general_ci ;

SET FOREIGN_KEY_CHECKS = 1;

那些触发器运行成功并且数据已经备份。但是我发现在MysqL显示死锁的日志。这里是日志。

------------------------
LATEST DETECTED DEADLOCK
------------------------
2020-08-11 16:45:04 7fabd105d700
*** (1) TRANSACTION:
TRANSACTION 6515932,ACTIVE 0 sec fetching rows 
MysqL tables in use 2,locked 2
LOCK WAIT 5 lock struct(s),heap size 1184,3 row lock(s),undo log entries 1 
MysqL thread id 2881920,OS thread handle 0x7fabcbcb2700,query id 32975223 192.159.41.218 sspreport Sending data 
update s_report   
    set 
      case_tracking_status = '7'
    where report_id = '111111'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 164 page no 3 n bits 72 index `PRIMARY` of table `test`.`s_report_back_up` trx id 6515932 lock_mode X locks rec but not gap waiting
Record lock,heap no 3 PHYSICAL RECORD: n_fields 49; compact format; info bits 0  

*** (2) TRANSACTION:
TRANSACTION 6515928,ACTIVE 0 sec starting index read 
MysqL tables in use 2,locked 2
7 lock struct(s),4 row lock(s),undo log entries 5  
MysqL thread id 2778519,OS thread handle 0x7fabd105d700,query id 32975231 192.159.41.240 sspfront Sending data  
update s_report        
     SET case_tracking_status = '12'  where report_id = '22222222'
*** (2) HOLDS THE LOCK(S):     
RECORD LOCKS space id 164 page no 3 n bits 72 index `PRIMARY` of table `test`.`s_report_back_up` trx id 6515928 lock_mode X locks rec but not gap 
Record lock,heap no 3 PHYSICAL RECORD: n_fields 49; compact format; info bits 0   
 

*** (2) WAITING FOR THIS LOCK TO BE GRANTED:  
RECORD LOCKS space id 164 page no 3 n bits 72 index `PRIMARY` of table `suishoupai`.`s_report_back_up` trx id 6515928 lock_mode X locks rec but not gap waiting
Record lock,heap no 2 PHYSICAL RECORD: n_fields 49; compact format; info bits 0 


*** WE ROLL BACK TRANSACTION (1) 
------------
TRANSACTIONS
------------

所以我不知道为什么会发生,死锁不应该在同一张桌子上发生吗?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)