数据库表创建-消息回执
版本归属
用于 v7 扩展架构版。
表清单
message_receipts
message_receipts
消息回执表。用于记录某条消息对某个用户的未读和已读状态。
执行 SQL
sql
CREATE TABLE IF NOT EXISTS message_receipts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
message_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
status ENUM('unread', 'read') NOT NULL DEFAULT 'unread',
updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY uk_message_receipts_message_user (message_id, user_id)
);字段说明:
id:回执记录 IDmessage_id:消息 IDuser_id:接收方用户 IDstatus:回执状态,unread表示未读,read表示已读updated_at:状态更新时间
索引说明:
uk_message_receipts_message_user:保证一条消息对一个用户只有一条回执记录
业务约束:
- v3 阶段使用
conversation_members.last_read_message_id做会话级已读 - v7 才启用
message_receipts做逐条消息已读/未读详情 - 没有回执记录时也可视为未读;显式
unread用于把某条消息标回未读 - 查询某条消息已读成员时按
message_id查询status = 'read'
建表后检查
sql
DESC message_receipts;
SHOW INDEX FROM message_receipts;最小验证
以下 SQL 假设 messages 表中已经存在 id = 1 的消息,users 表中已经存在 id = 2 的接收用户。
写入未读回执:
sql
INSERT INTO message_receipts (message_id, user_id, status)
VALUES (1, 2, 'unread');用户已读时更新状态:
sql
INSERT INTO message_receipts (message_id, user_id, status)
VALUES (1, 2, 'read')
ON DUPLICATE KEY UPDATE
status = 'read',
updated_at = CURRENT_TIMESTAMP;查询消息已读用户:
sql
SELECT user_id, status, updated_at
FROM message_receipts
WHERE message_id = 1 AND status = 'read';用户标回未读:
sql
INSERT INTO message_receipts (message_id, user_id, status)
VALUES (1, 2, 'unread')
ON DUPLICATE KEY UPDATE
status = 'unread',
updated_at = CURRENT_TIMESTAMP;代码落地点
models/message_receipt_model.go定义MessageReceipt- WebSocket 投递只负责实时消息下发,不自动写入回执
- 客户端读到消息后写入或更新为
read - 客户端需要标回未读时写入或更新为
unread - 查询回执前必须校验当前用户是消息所属会话成员