如何每秒从MySQL数据库拉取数据实现聊天应用消息自动更新
聊天应用自动拉取新消息实现方案
实现自动更新有两种常用方案,这里优先提供改造成本最低的短轮询方案,适合流量不大的个人项目使用:
1. 拆分独立后端查询接口
把消息/聊天列表的查询逻辑抽成单独的PHP文件,避免每次更新都要加载整个页面的内容,这里以消息查询为例,新建get_messages.php,代码如下:
<?php // 复用你原项目的数据库连接配置即可 $db = [你的数据库连接实例]; if (!isset($_GET['id']) || !preg_match("/^[0-9]+$/", $_GET['id'])) { echo json_encode(['code' => 400, 'msg' => '参数非法']); exit; } $user_id = intval($_GET['id']); // 新增last_id参数,仅拉取上次查询之后新增的消息,减少数据传输 $last_msg_id = isset($_GET['last_id']) ? intval($_GET['last_id']) : 0; // 改用预处理绑定参数,修复原代码的SQL注入风险 $fetch_sql = "SELECT * FROM users_messages WHERE (from_user=? OR to_user=?) AND id > ? ORDER BY id ASC"; $stmt = $db->prepare($fetch_sql); $stmt->execute([$user_id, $user_id, $last_msg_id]); $new_messages = $stmt->fetchAll(PDO::FETCH_ASSOC); echo json_encode([ 'code' => 200, 'new_last_id' => empty($new_messages) ? $last_msg_id : end($new_messages)['id'], 'data' => $new_messages ]); ?>
如果需要自动更新#autodata里的聊天用户列表,也可以用同样的逻辑,把用户列表的查询抽成独立接口即可。
2. 前端新增定时拉取逻辑
在你的聊天页面底部加入如下JS代码,定时拉取新数据更新页面:
// 记录上次拉取的最大消息ID let lastMsgId = 0; // 取当前聊天用户ID const currentChatId = new URLSearchParams(window.location.search).get('id'); // 当前登录用户ID,替换为你项目里的登录用户ID变量 const loginUserId = <?php echo $user_id; ?>; // 消息列表容器,替换为你实际的消息列表DOM ID const msgContainer = document.querySelector('#message-list'); function loadNewMsg() { if (!currentChatId) return; fetch(`get_messages.php?id=${currentChatId}&last_id=${lastMsgId}`) .then(res => res.json()) .then(res => { if (res.code !== 200 || res.data.length === 0) return; // 更新最新消息ID lastMsgId = res.new_last_id; // 渲染新消息到页面 res.data.forEach(item => { const msgDom = document.createElement('div'); // 根据消息发送方添加不同样式 msgDom.className = item.from_user == loginUserId ? 'my-message' : 'other-message'; // 替换为你数据库中存储消息内容的字段名 msgDom.innerText = item.content; msgContainer.appendChild(msgDom); }); // 自动滚动到消息列表底部 msgContainer.scrollTop = msgContainer.scrollHeight; }) } // 页面加载先拉一次历史消息 loadNewMsg(); // 每3秒拉一次新消息,可根据需求调整间隔时长 setInterval(loadNewMsg, 3000);
优化建议
- 原代码直接将用户输入的参数拼接进SQL语句,存在严重的SQL注入风险,所有数据库查询操作都建议改成预处理绑定参数的写法
- 若后续项目用户量上涨,可改用WebSocket方案实现服务端主动推送,性能远高于轮询,可使用Workerman、Swoole等PHP扩展快速实现
- 可新增未读消息计数逻辑,用户未打开对应聊天窗口时提示未读消息数量
内容的提问来源于stack exchange,提问作者Abderrahmane Bourri
相关产品推荐
相关产品推荐

