小程序后端绕不开数据库。选 MySQL 还是 MongoDB?连接怎么管?SQL 注入怎么防?这篇用一个真实的"用户 + 订单"模型,把小程序后端数据库的选型、连接、防护、备份整套方案讲透。
一、选型:什么项目用什么数据库
| 场景 | 推荐 | 理由 |
|---|---|---|
| 有订单/用户/商品等结构化数据 | MySQL 8 | 事务、关联查询、生态成熟 |
| 高频读的会话/缓存 | Redis | 微秒级读取,扛 token 和热点数据 |
| 日志/埋点/行为数据 | MongoDB 或直接 ES | 写入无模式,查询灵活 |
| 配置类小数据 | 应用内 JSON / SQLite | 别为十个配置起个库 |
90% 的小程序用 MySQL + Redis 就够了,别一上来就堆技术栈。小程序云开发用的是文档型数据库(类 MongoDB),没有事务和复杂关联——这也是云开发 vs 自建后端里劝你"正式项目自建"的原因之一。
二、MySQL 基础配置
1. 建库建账号(别用 root 跑业务):
CREATE DATABASE miniapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'app'@'127.0.0.1' IDENTIFIED BY '强密码';
GRANT SELECT, INSERT, UPDATE, DELETE ON miniapp.* TO 'app'@'127.0.0.1';
FLUSH PRIVILEGES;三个要点:utf8mb4(支持 emoji,utf8 会截断)、localhost only(数据库不对公网开放)、最小权限(业务账号不给 DDL 权限,见数据库安全加固与权限最小化)。
2. Docker 起一个 MySQL:
services:
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 强密码
MYSQL_DATABASE: miniapp
command: --default-authentication-plugin=caching_sha2_password
volumes: ["db-data:/var/lib/mysql"]
restart: unless-stopped
volumes:
db-data:3. 参数调优(2核4G 机器参考):
[mysqld]
innodb_buffer_pool_size = 1G # 内存的 50-60% 给缓冲池
max_connections = 200 # 小程序并发通常 < 100
innodb_flush_log_at_trx_commit = 2 # 性能与安全的折中完整调优见MySQL 安装与优化入门。
三、连接管理:连接池是生命线
反面教材——每个请求建一次连接:
// 错误:高并发下把 MySQL 连接数打满,直接 "Too many connections"
app.get('/api/list', async (req, res) => {
const conn = await mysql.createConnection(dbConfig)
const [rows] = await conn.query('SELECT * FROM posts LIMIT 20')
await conn.end()
res.json(rows)
})正确做法——连接池,整个应用共享:
const mysql = require('mysql2/promise')
const pool = mysql.createPool({
host: '127.0.0.1',
user: 'app',
password: '强密码',
database: 'miniapp',
waitForConnections: true,
connectionLimit: 20, // 池大小 ≈ max_connections 的 1/4 到 1/2
queueLimit: 0,
charset: 'utf8mb4'
})
app.get('/api/list', async (req, res) => {
const [rows] = await pool.query('SELECT id, title FROM posts WHERE status=? LIMIT ?', [1, 20])
res.json(rows)
})池大小怎么定:connectionLimit × 应用实例数 < max_connections × 0.8。留 20% 余量给运维和后台任务。
四、SQL 注入:参数化查询没有例外
小程序后端面对公网,所有用户输入都不可信。注入的经典后果是拖库——用户的手机号、订单全泄露。
// 危险:字符串拼接,输入 ' OR 1=1 -- 直接穿
const sql = `SELECT * FROM users WHERE phone = '${phone}'`
// 安全:参数化,驱动层处理转义
const [rows] = await pool.query('SELECT * FROM users WHERE phone = ?', [phone])
// 动态条件也安全(注意 LIMIT 的参数化)
const conditions = ['status = ?']
const params = [1]
if (req.query.keyword) {
conditions.push('title LIKE ?')
params.push(`%${req.query.keyword}%`)
}
const [rows] = await pool.query(
`SELECT id, title FROM posts WHERE ${conditions.join(' AND ')} LIMIT ?`,
[...params, 20]
)三条铁律:
- 永远参数化,ORM(Sequelize/TypeORM/Prisma)同理
- 绝不拼接 SQL,包括 ORDER BY 字段名(白名单校验)
- 错误信息别返回给前端——
err.message里的表结构是给攻击者的礼物,统一返回"服务器错误"
配套防护:WAF 规则过滤常见注入特征,见WAF 规则实战和网站常见漏洞与基础防护。
五、Redis:会话和缓存的标配
小程序登录态放 Redis 是标准姿势:
const { createClient } = require('redis')
const redis = createClient({ url: 'redis://:强密码@127.0.0.1:6379' })
await redis.connect()
// 登录:签发 token 存 Redis,2 小时过期
await redis.set('token:' + token, openid, { EX: 7200 })
// 鉴权中间件
app.use(async (req, res, next) => {
const token = req.headers.authorization?.replace('Bearer ', '')
const openid = await redis.get('token:' + token)
if (!openid) return res.status(401).json({ error: '未登录' })
req.openid = openid
next()
})Redis 必须设密码——没密码的 Redis 是公网扫描器的自助提权通道,见Redis 未授权访问防护。缓存雪崩防护(随机过期时间)见Redis 大 Key 与热 Key 处理。
六、备份:数据的最后防线
小程序后台的数据库是纯增量资产,丢了不可再生。三层备份:
# 1. 每日逻辑备份(crontab)
0 3 * * * mysqldump -u root -p强密码 --single-transaction --routines miniapp \
| gzip > /backup/miniapp-$(date +\%F).sql.gz
# 2. 异地一份(另一台机器或对象存储)
rsync -az /backup/ user@备份机:/backup/miniapp/
# 3. binlog 开启,支持时间点恢复binlog 时间点恢复的完整操作见MySQL 备份与恢复实战。每周做一次恢复演练——没验证过的备份等于没有备份。
七、性能 checklist
- [ ] 连接池已启用,池大小合理
- [ ] 查询字段具体化(别
SELECT *,大文本列拖慢 IO) - [ ] 高频查询走索引,
EXPLAIN验证,慢查询治理见MySQL 慢查询优化实战 - [ ] 热点数据进 Redis,数据库只兜底
- [ ] 深分页用游标(
WHERE id < ?)替代大 OFFSET - [ ] 每日备份 + 异地 + 恢复演练
结语
小程序数据库的技术核心就四件事:选对型、管好连接、防住注入、备好数据。MySQL + Redis + 连接池 + 参数化查询,这一套组合能扛住日活十万级的小程序,而且是每个后端的基本功,没有玄学。
需要搭小程序数据库服务器,可以看看财富云计算:NAT 型云服务器支持 443 映射,SSD 盘扛数据库随机读写,快照 + 自动备份随打随走,4核8G 档跑 MySQL + Redis 毫无压力,价格比独立 IP 机型省一半以上。
延伸阅读
- 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
- 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
- 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
- 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
- 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
- RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
- 短链接服务搭建:Shlink 自托管,链接数据自己掌握
- 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道

[...]netsh advfirewall firewall add rule name="GameRange" dir=in action=allow protocol=UDP localport=26901-26903完整的 Windows 环境准备(远程桌面连接、运行库安装、SteamCMD 用法、开机自启、8 个常见坑)见:《Windows 云服务器开服通用前置教程》→ htt[...]
2026-10-18 回复