You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

删除MySQL sourceTable时logTable的SourceId被随机置空问题排查

问题

执行MySQL循环删除操作时出现异常,使用以下存储过程删除sourceTable中6个月前的数据:

drop procedure if exists del_6m_data;

delimiter $$

create procedure del_data(table_name text, col_name text, del_limit text)

begin
    set @query = concat('delete from ', table_name, ' where ', col_name, ' < date_sub(current_date, INTERVAL 6 MONTH) limit ', del_limit);

    prepare query from @query;
    repeat
        execute query;
    until row_count() = 0 end repeat;

deallocate prepare query;

end $$

delimiter ;

两张表均为InnoDB引擎:

  • sourceTable存储当日待处理信息,ID为自增int类型;
  • logTable通过SourceId记录相关交互、结果等日志,DDL中未定义SourceId的外键关联及更新/删除规则。

异常现象:删除sourceTable数据时,logTable的SourceId被随机置空。已检查information_schema中的约束、存储过程、更新/删除规则,均未发现异常。logTable表结构如下:

CREATE TABLE `LogTable` (
  `id` int NOT NULL AUTO_INCREMENT,
  `state` int DEFAULT NULL,
  `statedesc` varchar(255) DEFAULT NULL,
  `scheduledat` datetime DEFAULT NULL,
  `countbusyretry` int DEFAULT '0',
  `countcongestionretry` int DEFAULT '0',
  `countnoanswerretry` int DEFAULT '0',
  `countglobal` int DEFAULT '0',
  `uniqueid` varchar(255) DEFAULT NULL,
  `originatecalleridnum` varchar(255) DEFAULT NULL,
  `originatecalleridname` varchar(255) DEFAULT NULL,
  `calleridnum` varchar(255) DEFAULT NULL,
  `calleridname` varchar(255) DEFAULT NULL,
  `starttime` datetime DEFAULT NULL,
  `responsetime` datetime DEFAULT NULL,
  `answertime` datetime DEFAULT NULL,
  `droptime` datetime DEFAULT NULL,
  `endtime` datetime DEFAULT NULL,
  `ringtime` int DEFAULT '0',
  `holdtime` int DEFAULT '0',
  `talktime` int DEFAULT '0',
  `followuptime` int DEFAULT '0',
  `dropreason` varchar(255) DEFAULT NULL,
  `campaign` varchar(255) DEFAULT NULL,
  `campaigntype` varchar(255) DEFAULT NULL,
  `membername` varchar(255) DEFAULT NULL,
  `reason` varchar(255) DEFAULT NULL,
  `disposition` varchar(255) DEFAULT NULL,
  `secondDisposition` varchar(255) DEFAULT NULL,
  `thirdDisposition` varchar(255) DEFAULT NULL,
  `dispositionat` datetime DEFAULT NULL,
  `amd` tinyint(1) DEFAULT '0',
  `fax` tinyint(1) DEFAULT '0',
  `blacklist` tinyint(1) DEFAULT '0',
  `rescheduled` tinyint(1) DEFAULT '0',
  `rescheduledat` datetime DEFAULT NULL,
  `callback` tinyint(1) DEFAULT '0',
  `callbackuniqueid` varchar(255) DEFAULT NULL,
  `callbackat` datetime DEFAULT NULL,
  `deleted` varchar(255) DEFAULT NULL,
  `deletedat` datetime DEFAULT NULL,
  `recallme` tinyint(1) DEFAULT '0',
  `agiafterat` datetime DEFAULT NULL,
  `createdAt` datetime NOT NULL,
  `updatedAt` datetime NOT NULL,
  `UserId` int DEFAULT NULL,
  `QueueId` int DEFAULT NULL,
  `SourceId` int DEFAULT NULL,
  `CampaignId` int DEFAULT NULL,
  `ListId` int DEFAULT NULL,
  `countnosuchnumberretry` int DEFAULT '0',
  `countdropretry` int DEFAULT '0',
  `countabandonedretry` int DEFAULT '0',
  `countmachineretry` int DEFAULT '0',
  `countagentrejectretry` int DEFAULT '0',
  PRIMARY KEY (`id`,`createdAt`),
  KEY `UserId` (`UserId`),
  KEY `QueueId` (`QueueId`),
  KEY `SourceId` (`SourceId`),
  KEY `CampaignId` (`CampaignId`),
  KEY `ListId` (`ListId`),
  KEY `calleridnum` (`calleridnum`),
  KEY `uniqueid` (`uniqueid`)
) ENGINE=InnoDB AUTO_INCREMENT=43886133 DEFAULT CHARSET=utf8mb3
/*!50100 PARTITION BY RANGE (to_days(`createdAt`))
(PARTITION px0Past VALUES LESS THAN (0) ENGINE = InnoDB,
 PARTITION px202207 VALUES LESS THAN (738733) ENGINE = InnoDB,
 PARTITION px202309 VALUES LESS THAN (739159) ENGINE = InnoDB,
 PARTITION px202310 VALUES LESS THAN (739190) ENGINE = InnoDB,
 PARTITION px202311 VALUES LESS THAN (739220) ENGINE = InnoDB,
 PARTITION px202312 VALUES LESS THAN (739251) ENGINE = InnoDB,
 PARTITION px202401 VALUES LESS THAN (739282) ENGINE = InnoDB,
 PARTITION px202402 VALUES LESS THAN (739311) ENGINE = InnoDB,
 PARTITION px9Future VALUES LESS THAN MAXVALUE ENGINE = InnoDB) */

需排查异常原因:是否存在隐藏约束导致此问题?

排查分析与结论
  • 排除隐藏外键约束:可执行以下SQL再次确认是否存在未显式定义的外键:

    SELECT * FROM information_schema.KEY_COLUMN_USAGE 
    WHERE REFERENCED_TABLE_NAME = 'sourceTable' AND TABLE_NAME = 'logTable';
    

    从提供的logTable DDL来看,确实没有定义外键关联,因此隐藏约束导致该问题的可能性极低。

  • 优先排查触发器与业务逻辑:
    存储过程仅对sourceTable执行删除操作,需检查是否存在针对sourceTable的AFTER DELETE触发器,逻辑中错误将logTable的SourceId置空。执行以下SQL查看触发器:

    SHOW TRIGGERS LIKE 'sourceTable';
    

    同时需排查应用层代码,是否在删除sourceTable数据时,额外执行了更新logTable的操作,导致SourceId被误置空。

  • 分区表与并发操作影响:
    logTable是按createdAt分区的大表,若删除操作执行时存在其他批量更新logTable的并发事务,可能因锁冲突、事务隔离级别问题导致数据不一致。可查看数据库错误日志、慢查询日志,排查操作时段是否有异常SQL执行记录。

  • 数据类型与索引异常:
    SourceId为允许NULL的int类型,需确认应用层在处理关联数据时,是否因查询不到sourceTable的对应ID,错误将logTable的SourceId更新为NULL;同时检查SourceId索引是否存在异常,避免批量操作时更新范围错误。

  • InnoDB事务机制问题:
    若删除操作在事务中执行,需检查是否因事务未正确提交、锁等待超时等问题,导致数据更新异常。可在测试环境单独执行存储过程,观察是否会触发logTable的SourceId置空,排除并发操作的干扰。

总结:该异常大概率由未被发现的触发器、应用层逻辑误操作,或并发事务冲突导致,而非隐藏约束。建议优先排查触发器与应用代码,再逐步验证分区表、事务等场景。

内容的提问来源于stack exchange,提问作者chrisiank

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 08:09:52