-- 可靠审计 Outbox、消费幂等和死信补偿增量(MySQL 8) SET NAMES utf8mb4; USE baiyue_audit; DROP PROCEDURE IF EXISTS create_reliable_audit_outbox; DELIMITER $$ CREATE PROCEDURE create_reliable_audit_outbox(IN schema_name VARCHAR(64)) BEGIN SET @ddl = CONCAT( 'CREATE TABLE IF NOT EXISTS \`', schema_name, '\`.sys_audit_outbox (', 'event_id VARCHAR(64) NOT NULL,event_type VARCHAR(64) NOT NULL,resource_type VARCHAR(64) NOT NULL,', 'resource_id VARCHAR(128) NULL,service_name VARCHAR(64) NULL,payload_json JSON NOT NULL,', 'status VARCHAR(16) NOT NULL DEFAULT ''PENDING'',attempt_count INT NOT NULL DEFAULT 0,', 'compensation_count INT NOT NULL DEFAULT 0,next_retry_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),', 'lease_owner VARCHAR(128) NULL,lease_until DATETIME(3) NULL,last_error VARCHAR(1000) NULL,', 'dead_at DATETIME(3) NULL,sent_at DATETIME(3) NULL,created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),', 'updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),', 'PRIMARY KEY(event_id),KEY idx_audit_outbox_publish(status,next_retry_at,lease_until,created_at),', 'KEY idx_audit_outbox_retention(status,sent_at)) ENGINE=InnoDB COMMENT=''可靠审计事件本地发送箱''' ); PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt; END$$ DELIMITER ; CALL create_reliable_audit_outbox('baiyue_auth'); CALL create_reliable_audit_outbox('baiyue_iam'); CALL create_reliable_audit_outbox('baiyue_order'); CALL create_reliable_audit_outbox('baiyue_firstleg'); CALL create_reliable_audit_outbox('baiyue_warehouse'); DROP PROCEDURE IF EXISTS create_reliable_audit_outbox; USE baiyue_audit; DROP PROCEDURE IF EXISTS add_audit_event_id; DELIMITER $$ CREATE PROCEDURE add_audit_event_id() BEGIN IF NOT EXISTS (SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA='baiyue_audit' AND TABLE_NAME='sys_audit_log' AND COLUMN_NAME='event_id') THEN ALTER TABLE sys_audit_log ADD COLUMN event_id VARCHAR(64) NULL COMMENT '审计事件全局唯一ID' AFTER id; END IF; IF NOT EXISTS (SELECT 1 FROM information_schema.STATISTICS WHERE TABLE_SCHEMA='baiyue_audit' AND TABLE_NAME='sys_audit_log' AND INDEX_NAME='uk_audit_event_id') THEN ALTER TABLE sys_audit_log ADD UNIQUE KEY uk_audit_event_id(event_id); END IF; END$$ DELIMITER ; CALL add_audit_event_id(); DROP PROCEDURE IF EXISTS add_audit_event_id; CREATE TABLE IF NOT EXISTS sys_audit_dead_letter ( id BIGINT NOT NULL AUTO_INCREMENT,event_id VARCHAR(64) NOT NULL,payload_text LONGTEXT NOT NULL, status VARCHAR(16) NOT NULL DEFAULT 'PENDING',retry_count INT NOT NULL DEFAULT 0, next_retry_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),lease_owner VARCHAR(128) NULL, lease_until DATETIME(3) NULL,last_error VARCHAR(1000) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),processed_at DATETIME(3) NULL, PRIMARY KEY(id),UNIQUE KEY uk_audit_dead_event(event_id), KEY idx_audit_dead_retry(status,next_retry_at,lease_until) ) ENGINE=InnoDB COMMENT='审计消息死信补偿表'; SELECT 'PASS' AS migration_status,'可靠审计Outbox、幂等和死信补偿表已就绪' AS message;