结论: 服务器搭建数据库的标准流程是六步:安装 MySQL 8.4 → 跑 mysql_secure_installation 做安全初始化 → 创建业务库与专用用户并按最小权限授权 → 调整 my.cnf 关键参数(尤其 innodb_buffer_pool_size)→ 用 bind-address 与安全组限制远程访问 → 配置 mysqldump 定时备份。其中第三步的最小授权与第五步的访问控制,是数据库不被拖库的两道关键防线。
"搭建数据库"包含三层含义:把数据库软件装上、让它安全地对外提供服务、以及保证数据可恢复。只做第一层的新手占比很高,结果是数据库裸奔在公网,常见的结局是被扫描器发现后遭遇勒索(删库要求赎金)。本文聚焦"怎么装、怎么配、怎么备份"的具体操作,至于该选 MySQL 还是 PostgreSQL、该买多大规格,属于选型层面的另一个话题。
安装前:版本选择与两条技术路线
结论:通用业务选 MySQL 8.4 LTS,需要 JSONB、GIS 地理数据、复杂分析查询或自定义数据类型时选 PostgreSQL 16。 两者都在 Ubuntu 24.04 与 CentOS Stream 9 上提供了官方源,安装成本相当。截至 2026 年,MySQL 8.4 LTS 与 PostgreSQL 16 均为各自的稳定主力版本。
| 对比项 | MySQL 8.4 LTS | PostgreSQL 16 |
|---|---|---|
| 默认端口 | 3306 | 5432 |
| 配置文件 | /etc/mysql/mysql.conf.d/mysqld.cnf | /etc/postgresql/16/main/postgresql.conf |
| 客户端命令 | mysql -u 用户 -p | psql -U 用户 -d 库名 |
| 默认认证 | caching_sha2_password | scram-sha-256 |
| 权限模型 | 用户@主机 二维授权 | 角色(Role)+ pg_hba.conf 规则 |
| 逻辑备份工具 | mysqldump | pg_dump / pg_dumpall |
| 突出优势 | 生态广、运维资料多、主从复制简单 | 复杂查询强、JSONB/GIS 原生、扩展丰富 |
| 典型场景 | WordPress、Spring Boot、电商 | GIS、数据仓库、金融风控 |
安装前还需确认磁盘规划:数据库数据目录应放在独立的数据盘上(如挂载到 /data/mysql),不要与系统盘共用。理由有两点:一是数据盘可单独扩容与做快照,二是日志与数据写满系统盘会直接导致 SSH 都无法登录。
第一步:安装 MySQL 8.4
结论:Ubuntu 24.04 官方源默认提供 MySQL 8.0.x,要装 8.4 LTS 必须添加 MySQL 官方 APT 仓库。 装完第一件事是确认服务状态与版本号,而不是急着建库。
# ===== Ubuntu 24.04:添加 MySQL 官方源 =====
wget https://dev.mysql.com/get/mysql-apt-config_0.8.30-1_all.deb
sudo dpkg -i mysql-apt-config_0.8.30-1_all.deb # 交互界面中选 mysql-8.4-lts
sudo apt update
sudo apt install -y mysql-server
sudo systemctl enable --now mysql
# ===== CentOS Stream 9 / Rocky Linux 9 =====
sudo dnf install -y https://dev.mysql.com/get/mysql84-community-release-el9-1.noarch.rpm
sudo dnf install -y mysql-community-server
sudo systemctl enable --now mysqld
# ===== 验证:确认版本与监听端口 =====
mysql --version
sudo systemctl status mysql --no-pager
sudo ss -lntp | grep 3306
# 若官方源不可用,退而求其次用系统源(版本为 8.0.x)
# sudo apt install -y mysql-serverCentOS 系首次启动会在 /var/log/mysqld.log 里生成 root 临时密码,用 sudo grep 'temporary password' /var/log/mysqld.log 取出后登录并立即修改。
第二步:执行安全初始化
结论:mysql_secure_installation 是装完数据库后必须立刻执行的脚本,它一次性完成设密码策略、删匿名用户、禁 root 远程登录、删 test 库四件事。 跳过这一步的数据库,等于默认允许任意来源尝试 root 登录。
sudo mysql_secure_installation交互选项建议如下:
- VALIDATE PASSWORD 组件:选
y。强制密码长度 ≥ 8 且含大小写、数字、符号。 - 密码强度等级:选
2(STRONG)。生产库不要用弱密码。 - Remove anonymous users?:选
y。匿名用户可被未授权访问利用。 - Disallow root login remotely?:选
y。root 仅允许localhost登录,是防止远程爆破的关键。 - Remove test database?:选
y。默认 test 库对所有用户可写。 - Reload privilege tables now?:选
y。让上述改动立即生效。
# 初始化后验证:root 只能本地登录
sudo mysql -e "SELECT user, host, plugin FROM mysql.user;"
# 正常应看到 root 对应 host 仅为 localhost第三步:创建数据库与用户并最小授权
结论:永远不要让你的应用直接用 root 连库。 正确做法是为每个业务创建独立数据库与独立用户,并且只授予它真正需要的那几种权限——只读服务只给 SELECT,业务服务给 SELECT, INSERT, UPDATE, DELETE,只有运维做 DDL 变更时才临时用管理账号。
-- 创建业务库:字符集统一用 utf8mb4,避免 emoji 与生僻字入库报错
CREATE DATABASE appdb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 创建应用账号:@'localhost' 表示仅允许本机连接
CREATE USER 'appuser'@'localhost'
IDENTIFIED BY 'Str0ng!Passw0rd#2026';
-- 最小授权:只给 DML,不给 DROP / ALTER / SUPER / FILE
GRANT SELECT, INSERT, UPDATE, DELETE ON appdb.* TO 'appuser'@'localhost';
-- 只读账号(给报表、BI 用)
CREATE USER 'report'@'%' IDENTIFIED BY 'An0ther!Str0ngPwd';
GRANT SELECT ON appdb.* TO 'report'@'%';
FLUSH PRIVILEGES;
-- 核对授权结果
SHOW GRANTS FOR 'appuser'@'localhost';授权时有三条红线要守住:
- **不要写
GRANT ALL PRIVILEGES ON .**:一旦应用被注入,.意味着攻击者能读走同实例上所有库。 - 不要授予
FILE、SUPER、PROCESS:这些权限可用于写文件和读取其他连接信息,是提权跳板。 - 主机位不要用
%通配:'appuser'@'%'表示允许从任意 IP 连接,应改成具体内网 IP 段,如'appuser'@'10.0.0.%'。
第四步:调整关键配置参数
结论:默认配置是按极小内存机器设计的,必须根据服务器规格调整,其中 innodb_buffer_pool_size 影响最大。 缓冲池(Buffer Pool)是 InnoDB 缓存数据与索引的内存区域,命中率直接决定磁盘 IO 压力。
# /etc/mysql/mysql.conf.d/mysqld.cnf (Ubuntu 24.04)
[mysqld]
# 数据目录:建议指向独立数据盘
datadir = /data/mysql
# 缓冲池:独占数据库服务器设为物理内存的 50%~70%
# 8G 机器设 5G,4G 机器设 2G;与应用同机部署时降到 40% 以下
innodb_buffer_pool_size = 5G
innodb_buffer_pool_instances = 4
# 连接与超时
max_connections = 300
wait_timeout = 600
interactive_timeout = 600
# 字符集与时区
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
default-time-zone = '+08:00'
# 持久化与性能权衡:1 为最安全(每次提交落盘),2 为每秒刷一次
innodb_flush_log_at_trx_commit = 1
innodb_log_file_size = 512M
# 慢查询日志:定位慢 SQL 的基础
slow_query_log = 1
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time = 2
# 每个连接的排序缓冲,不宜设大,否则并发时内存暴涨
sort_buffer_size = 2M
join_buffer_size = 2M修改后必须校验并重启(注意:innodb_buffer_pool_size 等参数需重启才生效,不能用 reload):
sudo mysqld --help --verbose 2>/dev/null | grep -i 'buffer pool' # 查默认值参考
sudo systemctl restart mysql
sudo mysql -e "SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'max_connections';
SHOW VARIABLES LIKE 'slow_query_log';"第五步:远程访问的安全配置
结论:数据库端口绝不应直接对公网开放。bind-address 决定 MySQL 监听哪个网卡,配合云平台安全组限制来源 IP,才是安全的远程访问方式;更推荐的做法是用 SSH 隧道或内网专线。
# 只监听本机:应用与数据库同机部署时用这个(默认值,最安全)
bind-address = 127.0.0.1
# 监听内网网卡:应用部署在其他服务器时,填数据库机的内网 IP
bind-address = 10.0.0.12
# 监听所有地址:等同于对全网开放,禁止在生产环境使用
# bind-address = 0.0.0.0# 修改后重启生效
sudo systemctl restart mysql
sudo ss -lntp | grep 3306 # 确认监听地址已变更
# 防火墙只放行来自应用服务器内网 IP 的连接
sudo ufw allow from 10.0.0.20 to any port 3306 proto tcp
# firewalld 写法:
# sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" \
# source address="10.0.0.20" port port="3306" protocol="tcp" accept'
# sudo firewall-cmd --reload
# 从应用机测试连通性
mysql -h 10.0.0.12 -u appuser -p -e "SELECT 1;"若必须跨公网管理数据库,请用 SSH 隧道代替开放端口:本地执行 ssh -L 3307:127.0.0.1:3306 user@dbserver,然后连接本机的 3307 端口,全程走加密的 SSH 通道,数据库端口无需暴露。
第六步:备份与恢复
结论:没有备份的数据库等于没有数据。mysqldump 是逻辑备份的标准工具,配合 crontab 每天全量 + 保留 7~30 天,是中小规模最实用的方案。
# 全库备份:--single-transaction 保证 InnoDB 一致性且不锁表
mysqldump -u root -p --single-transaction --routines --triggers --events \
--set-gtid-purged=OFF appdb | gzip > /backup/appdb_$(date +%F).sql.gz
# 全实例备份(含所有库与用户权限)
mysqldump -u root -p --all-databases --single-transaction \
--routines --triggers --events | gzip > /backup/all_$(date +%F).sql.gz
# 恢复:先解压再导入
gunzip < /backup/appdb_2026-03-15.sql.gz | mysql -u root -p appdb
# 只备份表结构(用于建测试库)
mysqldump -u root -p --no-data appdb > /backup/appdb_schema.sql
# 加入定时任务:每天凌晨 2 点全量备份,保留 14 天
sudo crontab -e
0 2 * * * mysqldump -u root -p'密码' --single-transaction appdb | gzip > /backup/appdb_$(date +\%F).sql.gz
0 3 * * * find /backup -name "appdb_*.sql.gz" -mtime +14 -delete把密码明文写进 crontab 有泄露风险,更好的方式是把凭据写进 ~/.my.cnf(权限 600)并在命令里省略 -p:
# ~/.my.cnf
[mysqldump]
user=root
password=Str0ng!Passw0rd
企业QQ咨询




