-- Split message body by conversation type. Snowflake MsgId remains PK / sort / sync cursor. CREATE TABLE IF NOT EXISTS private_message ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属单聊会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id;系统消息为 0', receiver_id BIGINT NOT NULL DEFAULT 0 COMMENT '接收者 user_id;系统消息为 0', client_msg_id VARCHAR(64) NOT NULL COMMENT '客户端消息 id,与 sender+会话 组成幂等键', message_type SMALLINT NOT NULL COMMENT '消息类型:1文本 2图片 3语音 4视频 5表情 6GIF 7文件 8位置 9系统', content BLOB NOT NULL COMMENT '序列化后的消息体(JSON 字节),禁止存原始 string;媒体只存对象存储 key', status TINYINT NOT NULL DEFAULT 1 COMMENT '1=正常 2=已撤回 3=审核隐藏', created_at DATETIME(3) NOT NULL COMMENT '服务端入库时间', UNIQUE KEY uk_sender_conv_client_msg (sender_id, conversation_id, client_msg_id), KEY idx_conversation_id (conversation_id, id), KEY idx_receiver_id (receiver_id, id) ) COMMENT='单聊消息正文。PK=MsgId;与 group_message 分表存储'; CREATE TABLE IF NOT EXISTS group_message ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属群会话 id', group_id BIGINT NOT NULL DEFAULT 0 COMMENT '群号 groups.id,便于按群查询', sender_id BIGINT NOT NULL COMMENT '发送者 user_id;系统消息为 0', client_msg_id VARCHAR(64) NOT NULL COMMENT '客户端消息 id,与 sender+会话 组成幂等键', message_type SMALLINT NOT NULL COMMENT '消息类型:1文本 2图片 3语音 4视频 5表情 6GIF 7文件 8位置 9系统', content BLOB NOT NULL COMMENT '序列化后的消息体(JSON 字节),禁止存原始 string;媒体只存对象存储 key', status TINYINT NOT NULL DEFAULT 1 COMMENT '1=正常 2=已撤回 3=审核隐藏', created_at DATETIME(3) NOT NULL COMMENT '服务端入库时间', UNIQUE KEY uk_sender_conv_client_msg (sender_id, conversation_id, client_msg_id), KEY idx_conversation_id (conversation_id, id), KEY idx_group_id (group_id, id) ) COMMENT='群聊消息正文。PK=MsgId;群热路径不写 MySQL inbox 行'; CREATE TABLE IF NOT EXISTS messages ( id BIGINT PRIMARY KEY COMMENT 'Snowflake MsgId,主键、排序键、同步游标', conversation_id BIGINT NOT NULL COMMENT '所属会话 id', sender_id BIGINT NOT NULL COMMENT '发送者 user_id', client_msg_id VARCHAR(64) NOT NULL COMMENT '客户端消息 id,与 sender+会话 组成幂等键', message_type SMALLINT NOT NULL COMMENT '消息类型:1文本 2图片 3语音 4视频 5表情 6GIF 7文件 8位置 9系统', content BLOB NOT NULL COMMENT '序列化后的消息体(JSON 字节),禁止存原始 string;媒体只存对象存储 key', status TINYINT NOT NULL DEFAULT 1 COMMENT '1=正常 2=已撤回 3=审核隐藏', created_at DATETIME(3) NOT NULL COMMENT '服务端入库时间', UNIQUE KEY uk_sender_conv_client_msg (sender_id, conversation_id, client_msg_id), KEY idx_conversation_id (conversation_id, id) ) COMMENT='迁移中转表。0011 拷贝到 private_message / group_message 后删除'; INSERT IGNORE INTO private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at FROM messages m INNER JOIN conversations c ON c.id = m.conversation_id AND c.type = 1; INSERT IGNORE INTO group_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at FROM messages m INNER JOIN conversations c ON c.id = m.conversation_id AND c.type = 2; INSERT IGNORE INTO private_message (id, conversation_id, sender_id, client_msg_id, message_type, content, status, created_at) SELECT m.id, m.conversation_id, m.sender_id, m.client_msg_id, m.message_type, m.content, m.status, m.created_at FROM messages m LEFT JOIN conversations c ON c.id = m.conversation_id WHERE c.id IS NULL; DROP TABLE IF EXISTS messages;