单条sql去删除大量数据,会导致锁表,事务提交失败,一直执行10多个小时也没成功:
DELETE FROM AIMAS_ENGAGEMENT_STATS_STAGING  WHERE SOURCE_CREATE_TIME < CURDATE()

image

改造成服务去调存储过程,分批量删数据:

-- drop procedure proc_delete_dummy_comm_dtl;
CREATE PROCEDURE `proc_delete_dummy_comm_dtl`()
BEGIN
    -- 1. 定义变量
    DECLARE done INT DEFAULT 0;
    DECLARE v_row_id varchar(15);
    DECLARE v_count INT DEFAULT 0;
    DECLARE v_total_count INT DEFAULT 0;
    DECLARE v_batch_size INT DEFAULT 200; -- 每 100 条提交一次
    DECLARE v_mgr_queue_count BIGINT DEFAULT 0;
    DECLARE v_mgr_sleep_seconds INT DEFAULT 10;
    DECLARE v_mgr_threshold BIGINT DEFAULT 10000;
    DECLARE v_mgr_sleep_count INT DEFAULT 0;
    DECLARE has_error INT DEFAULT 0;
    
    -- 定义游标 (去掉了 LIMIT 7,以便处理所有数据,如需限制可加回)
    DECLARE cur CURSOR FOR 
select a.row_id from CUSTOMER_COMM_DTL a 
inner join CUSTOMER_COMMUNICATION b on a.par_row_id = b.COMMUNICATION_ID
inner join SUPPORT.DUMMY_MARKETING_OFFERS tmp on b.DCP_ID = tmp.CAMP_TRTM_ID
where tmp.END_DT= v_batch_size THEN
            START TRANSACTION;
            -- A. 执行delete(从原表关联临时表)
                    DELETE t 
FROM CUSTOMER_COMM_DTL t
INNER JOIN tmp_batch_pks tmp ON t.row_id = tmp.pk_val;
           
            -- C. 提交事务
            IF has_error = 0 THEN
                COMMIT;

                -- MGR事务延时检查
                BEGIN
                    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
                    SELECT SUM(COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE) INTO v_mgr_queue_count
                    FROM performance_schema.replication_group_member_stats
                    WHERE CHANNEL_NAME = 'group_replication_applier';
                    IF v_mgr_queue_count > v_mgr_threshold THEN
                        SET v_mgr_sleep_count = v_mgr_sleep_count + 1;
                        SELECT CONCAT('[MGR] Transaction queue delay detected: ', v_mgr_queue_count, 
                                      ' > ', v_mgr_threshold, ', sleeping ', v_mgr_sleep_seconds, 's... (sleep #', v_mgr_sleep_count, ')') AS MgrStatus;
                        DO SLEEP(v_mgr_sleep_seconds);
                    END IF;
                END;

                -- 可选:输出进度日志
                SELECT CONCAT('Batch committed: ', v_count,',Total committed: ',v_total_count) AS Info;
            ELSE
                -- 发生错误,Handler 已回滚,这里可以选择退出循环或继续
                -- 为了数据安全,建议遇到错误直接退出
                CLOSE cur;
                DROP TEMPORARY TABLE IF EXISTS tmp_batch_pks;
                SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'Error occurred during batch processing. Transaction rolled back.';
            END IF;
           
            -- D. 清空临时表并重置计数器
            TRUNCATE TABLE tmp_batch_pks;
            SET v_count = 0;
        END IF;
    END LOOP;

    CLOSE cur;

    -- 4. 【收尾】处理最后不足 100 条的剩余数据
    IF v_count > 0 THEN
        START TRANSACTION;
        
        -- delete
          DELETE t 
FROM CUSTOMER_COMM_DTL t
INNER JOIN tmp_batch_pks tmp ON t.row_id = tmp.pk_val;


        -- 提交
        IF has_error = 0 THEN
            COMMIT;

            -- MGR事务延时检查
            BEGIN
                DECLARE CONTINUE HANDLER FOR SQLEXCEPTION BEGIN END;
                SELECT SUM(COUNT_TRANSACTIONS_REMOTE_IN_APPLIER_QUEUE) INTO v_mgr_queue_count
                FROM performance_schema.replication_group_member_stats
                WHERE CHANNEL_NAME = 'group_replication_applier';
                IF v_mgr_queue_count > v_mgr_threshold THEN
                    SET v_mgr_sleep_count = v_mgr_sleep_count + 1;
                    SELECT CONCAT('[MGR] Transaction queue delay detected: ', v_mgr_queue_count, 
                                  ' > ', v_mgr_threshold, ', sleeping ', v_mgr_sleep_seconds, 's... (sleep #', v_mgr_sleep_count, ')') AS MgrStatus;
                    DO SLEEP(v_mgr_sleep_seconds);
                END IF;
            END;

            SELECT CONCAT('Final batch committed: ', v_count, ' rows.','Total committed: ',v_total_count,' rows.') AS Status;
        ELSE
            ROLLBACK;
            SELECT 'Final batch failed and rolled back.' AS Status;
       END IF;
    ELSE
        IF v_start IS NOT NULL THEN -- 避免空跑时输出
             SELECT 'Processing completed. No remaining records.' AS Status;
        END IF;
    END IF;

    -- 5. 清理临时表
    DROP TEMPORARY TABLE IF EXISTS tmp_batch_pks;
END;

 


原文地址: https://www.cveoy.top/t/topic/qHuu 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录