必须一步到位创建message_db数据库和messages表,严格按业务初始化结构,确保字段类型正确、status加索引、utf8mb4编码,并验证连接权限与配置。

创建 message_db 数据库和 messages 表必须一步到位
很多人在搭建时只建库不建表,或字段类型写错(比如用 TEXT 存短消息、漏掉 status 枚举约束),导致后续推送逻辑查不到未读消息。正确做法是严格按业务需要初始化结构:
CREATE DATABASE message_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;USE message_db;CREATE TABLE messages (id INT AUTO_INCREMENT PRIMARY KEY, content VARCHAR(255) NOT NULL, status ENUM('unread','read') DEFAULT 'unread', created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP);
注意:别用 TIMESTAMP 自动更新 created_at,否则状态变更时时间会被覆盖;utf8mb4 是必须的,否则 emoji 或某些中文会存成问号。
插入测试数据前先确认连接权限和用户密码
常见错误是本地开发用 root 连 MySQL,但生产环境禁止 root 远程登录,结果 go run migrate/migrate.go 报 Access denied for user 却卡在“数据库已存在”假象里。实操建议:
PHP商城系统是国内领先商城系统,网店系统,购物系统,网上商城系统,B2C商城系统产品.同时也是一个商业的PHP开发框架。PHP 商城系统由内容、文章、会员、留言、订单、 财务、广告、短消息、数据库管理、营销推广、内置支付管理、商品配送管理、无限级分类、全站搜索等多个功能模块插件组成。在当今瞬机万变的市场环境中,快速高效的IT解决方案是您业务成功的关键。我们PHP商城系统能为您量身打造完全符合需求
- 用
mysql -u your_username -p -h localhost手动连一次,验证账号密码和 host 权限 - 检查
conf/app.ini中的host是否写成127.0.0.1(部分 MySQL 安装默认禁用 localhost 的 socket 连接) - 如果用 Docker 启 MySQL,确保容器端口映射正确:
-p 3306:3306,且应用配置里的host填容器名(如mysql)而非localhost
查询 unread 消息必须加索引,否则高并发下直接拖垮服务
刚上线时几条测试数据看不出问题,一旦日均消息量过万,SELECT * FROM messages WHERE status = 'unread' 就会变慢查询。MySQL 默认不会给 status 字段自动建索引,必须手动补:
ALTER TABLE messages ADD INDEX idx_status (status);- 如果推送接口还按时间排序(如
ORDER BY created_at DESC),建议建联合索引:ADD INDEX idx_status_created (status, created_at) - 别在
content上建全文索引——消息推送几乎不搜内容,纯属浪费 I/O 和内存
用存储过程模拟队列出队要小心事务和锁
有人照搬 Redis 的 pop 模式,用 MySQL 写 SELECT ... FOR UPDATE + DELETE 实现“取一条删一条”,但在高并发下容易死锁或漏消息。更稳妥的做法是:
- 用单条原子语句完成“标记为已读并返回”:
UPDATE messages SET status = 'read' WHERE id = (SELECT id FROM messages WHERE status = 'unread' ORDER BY id ASC LIMIT 1) AND status = 'unread'; - 再用
SELECT查刚才更新的那条(需配合LAST_INSERT_ID()或应用层记录 ID) - 避免用
TRIGGER自动推 Redis——触发器内不能开新连接,也难调试;改用应用层轮询 +INSERT ... SELECT转存到专用队列表更可控
真正麻烦的不是建库建表,而是当推送量涨到每秒上百条时,status 字段的行锁竞争会让整个表卡住——这时候才意识到,一开始没加索引、没规划好读写分离,比重装 MySQL 还费时间。









