选 MySQL 还是 MariaDB

  • MySQL — Oracle 维护,社区版(Community)免费
  • MariaDB — MySQL 的开源分支,由 Monty(MySQL 原作者)维护

两者 API 高度兼容,绝大多数应用都能直接换。新项目两者都可以,看公司既有栈和团队习惯。本文以 MariaDB 为例(默认包更新)。

装 MariaDB

sudo apt update
sudo apt install mariadb-server mariadb-client

sudo systemctl enable --now mariadb
sudo systemctl status mariadb

安全初始化(必跑

sudo mysql_secure_installation

按提示选:

Switch to unix_socket authentication? [Y/n] Y
Change the root password? [Y/n] Y              ← 设密码
Remove anonymous users? [Y/n] Y
Disallow root login remotely? [Y/n] Y          ← 强烈推荐
Remove test database? [Y/n] Y
Reload privilege tables? [Y/n] Y

创建数据库 + 用户

sudo mysql -u root
-- 建库
CREATE DATABASE myapp CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

-- 建用户
CREATE USER 'myapp'@'localhost' IDENTIFIED BY 'StrongPassword!';

-- 授权
GRANT ALL PRIVILEGES ON myapp.* TO 'myapp'@'localhost';

-- 应用变更
FLUSH PRIVILEGES;

-- 验证
SHOW DATABASES;
SELECT user, host FROM mysql.user;

EXIT;

测试用新用户登录:

mysql -u myapp -p myapp

远程访问(小心配)

默认 MariaDB 只监听 127.0.0.1——外网连不上。

如果要远程连(不推荐生产直接开公网):

sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf
bind-address = 0.0.0.0
sudo systemctl restart mariadb

授权远程用户(指定来源 IP,不要 % 全开):

CREATE USER 'myapp'@'192.168.1.%' IDENTIFIED BY 'StrongPassword!';
GRANT ALL ON myapp.* TO 'myapp'@'192.168.1.%';
FLUSH PRIVILEGES;

防火墙开 3306:

sudo ufw allow from 192.168.1.0/24 to any port 3306

绝对不要 bind-address = 0.0.0.0 + 'myapp'@'%' + ufw 全开——一夜被扫库。

生产推荐:通过 SSH 隧道 / VPN / 内网 / 跳板机访问数据库,公网零暴露。

关键配置(性能)

/etc/mysql/mariadb.conf.d/50-server.cnf:

[mysqld]
# 字符集
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

# 连接数
max_connections = 200

# 内存(⚠ 按机器内存调,**别照抄**)
# 经验:调到机器可用内存的 50%–70%
# 4G 机器:1G–2G;8G:4G–6G;机器只有 1G 时设 256M 即可
innodb_buffer_pool_size = 1G
innodb_log_file_size = 256M

# 日志
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1                # 慢于 1 秒的查询记下来

# 二进制日志(主从复制 / 时间点恢复)
log_bin = /var/log/mysql/mysql-bin
expire_logs_days = 7

改完重启:

sudo systemctl restart mariadb

备份

mysqldump(小数据库)

# 备份单库
mysqldump -u root -p myapp > myapp-$(date +%F).sql

# 备份所有
mysqldump -u root -p --all-databases > all-$(date +%F).sql

# 压缩
mysqldump -u root -p myapp | gzip > myapp-$(date +%F).sql.gz

# 只结构 / 只数据
mysqldump --no-data myapp > schema.sql
mysqldump --no-create-info myapp > data.sql

恢复

mysql -u root -p myapp < myapp-2026-05-09.sql
gunzip < myapp-2026-05-09.sql.gz | mysql -u root -p myapp

大库用 mariabackup / Percona XtraBackup

sudo apt install mariadb-backup
sudo mariabackup --backup --target-dir=/backups/db --user=root --password=...

物理备份,不锁表,适合 GB 级以上。

监控

mysql -e "SHOW STATUS LIKE 'Threads_connected'"
mysql -e "SHOW PROCESSLIST"

# 慢查询
sudo tail -f /var/log/mysql/slow.log

# 错误日志
sudo tail -f /var/log/mysql/error.log

实战:自动化每日备份脚本

#!/bin/bash
set -euo pipefail

readonly DB="myapp"
readonly BACKUP_DIR="/backups/db"
readonly DATE=$(date +%F)
readonly KEEP_DAYS=14

mkdir -p "$BACKUP_DIR"

# 备份(密码从 ~/.my.cnf 读,**不要写命令行**)
mariadb-dump --single-transaction "$DB" | gzip > "$BACKUP_DIR/$DB-$DATE.sql.gz"

# 同步到对象存储
rclone copy "$BACKUP_DIR" r2:db-backup --include "*-$DATE.*"

# 清理旧的
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +$KEEP_DAYS -delete

echo "✓ Backup done: $BACKUP_DIR/$DB-$DATE.sql.gz"

~/.my.cnf(权限 600):

[client]
user=root
password=YourPassword

crontab:

0 3 * * * /usr/local/bin/db-backup.sh >> /var/log/db-backup.log 2>&1

几条生产建议

  • 数据库不要和应用同机器(如果资源允许)—— 容易互相 OOM
  • 生产用主从(master + slave 复制)—— 见 ops-corp/34-db-ha
  • 绝不裸密码远程—— SSH 隧道 / VPN / 私网
  • 托管 RDS / Aurora / 云数据库 通常比自己运维划算(前期值,规模后看)

下一篇:自动化备份系统(不只是数据库)。