fix: align private message ids with snowflake

This commit is contained in:
richjohnrambo
2026-09-27 02:53:25 +08:00
parent c8d08e26e2
commit ae2dc0d45e
3 changed files with 122 additions and 5 deletions
@@ -0,0 +1,69 @@
-- IM private-message Snowflake ID compatibility migration.
-- Scope: the shared business database (for example meeting_im).
-- Review and back up before execution. This script does not replay dead letters.
-- 1. Preflight: every listed id column must become BIGINT.
SELECT TABLE_NAME, COLUMN_TYPE, IS_NULLABLE, EXTRA
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND (TABLE_NAME = 'im_messages' OR TABLE_NAME REGEXP '^im_[0-9]+_messages$')
AND COLUMN_NAME = 'id'
ORDER BY TABLE_NAME;
-- 2. Upgrade the template/base table used by new tenant shards.
ALTER TABLE `im_messages`
MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT;
-- 3. Upgrade every existing tenant private-message shard.
DELIMITER $$
DROP PROCEDURE IF EXISTS migrate_private_message_id_to_bigint$$
CREATE PROCEDURE migrate_private_message_id_to_bigint()
BEGIN
DECLARE done INT DEFAULT 0;
DECLARE shard_table VARCHAR(64);
DECLARE shard_cursor CURSOR FOR
SELECT TABLE_NAME
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME REGEXP '^im_[0-9]+_messages$'
ORDER BY TABLE_NAME;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN shard_cursor;
shard_loop: LOOP
FETCH shard_cursor INTO shard_table;
IF done = 1 THEN
LEAVE shard_loop;
END IF;
SET @alter_message_id_sql = CONCAT(
'ALTER TABLE `', REPLACE(shard_table, '`', '``'),
'` MODIFY COLUMN `id` BIGINT NOT NULL AUTO_INCREMENT'
);
PREPARE alter_message_id_stmt FROM @alter_message_id_sql;
EXECUTE alter_message_id_stmt;
DEALLOCATE PREPARE alter_message_id_stmt;
END LOOP;
CLOSE shard_cursor;
END$$
CALL migrate_private_message_id_to_bigint()$$
DROP PROCEDURE migrate_private_message_id_to_bigint$$
DELIMITER ;
-- 4. Post-check: this query must return zero rows.
SELECT TABLE_NAME, COLUMN_TYPE, IS_NULLABLE, EXTRA
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = DATABASE()
AND (TABLE_NAME = 'im_messages' OR TABLE_NAME REGEXP '^im_[0-9]+_messages$')
AND COLUMN_NAME = 'id'
AND DATA_TYPE <> 'bigint';
-- 5. Observe pending recovery work. Replay only after the post-check passes.
SELECT status, last_reason, COUNT(*) AS message_count,
MIN(created_at) AS first_created_at, MAX(created_at) AS last_created_at
FROM im_kafka_dead_letters
WHERE event_type = 'message.persist.p2p'
GROUP BY status, last_reason
ORDER BY status, last_reason;