强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

Nextcloud 私有云部署教程 / 04 - 数据库管理

04 - 数据库管理

深入了解 Nextcloud 的数据库选型、配置优化、高可用架构以及备份恢复策略。


4.1 数据库选型概览

Nextcloud 支持三种数据库后端,选择直接影响性能与可扩展性:

特性SQLiteMySQL / MariaDBPostgreSQL
适用规模开发测试 / 单用户中小到大型部署中大型到企业级
并发性能优秀优秀
全文搜索基础支持支持(更强)
JSON 支持基础原生支持
安装复杂度零配置中等中等
复制 / HA不支持主从复制 / Galera流复制 / Patroni
Nextcloud 推荐❌ 仅测试✅ 推荐✅ 推荐
资源占用中等中等偏高

建议: 生产环境必须使用 MySQL/MariaDB 或 PostgreSQL。SQLite 仅用于快速体验或单元测试。


4.2 MySQL / MariaDB 配置

推荐版本

数据库推荐版本说明
MySQL8.0+推荐 8.0 或 8.4
MariaDB10.6+推荐 10.11 LTS

安装

# Ubuntu / Debian
sudo apt install -y mariadb-server mariadb-client

# 启动并设置开机自启
sudo systemctl enable --now mariadb

# 安全初始化
sudo mysql_secure_installation

创建数据库和用户

-- 登录
sudo mysql -u root -p

-- 创建数据库
CREATE DATABASE IF NOT EXISTS nextcloud
  CHARACTER SET utf8mb4
  COLLATE utf8mb4_general_ci;

-- 创建专用用户
CREATE USER IF NOT EXISTS 'ncuser'@'localhost'
  IDENTIFIED BY 'StrongPassword123!';

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

-- 如果使用 MySQL 8.0+,需要指定认证插件
ALTER USER 'ncuser'@'localhost'
  IDENTIFIED WITH mysql_native_password BY 'StrongPassword123!';

FLUSH PRIVILEGES;

MariaDB / MySQL 推荐配置

编辑 /etc/mysql/mariadb.conf.d/90-nextcloud.cnf(MariaDB)或 /etc/mysql/mysql.conf.d/nextcloud.cnf(MySQL):

[mysqld]
# ======== 存储引擎 ========
default_storage_engine = InnoDB
innodb_file_per_table = ON
innodb_large_prefix = ON
innodb_file_format = Barracuda

# ======== 字符集 ========
character-set-server = utf8mb4
collation-server = utf8mb4_general_ci

# ======== InnoDB 调优 ========
innodb_buffer_pool_size = 1G              # 建议为可用内存的 50-70%
innodb_buffer_pool_instances = 1          # buffer_pool_size > 1G 时设为多个
innodb_log_file_size = 256M
innodb_log_buffer_size = 64M
innodb_flush_log_at_trx_commit = 2        # 1=最安全 2=性能更好
innodb_flush_method = O_DIRECT
innodb_io_capacity = 2000                 # SSD 建议 2000-4000
innodb_io_capacity_max = 4000
innodb_read_io_threads = 4
innodb_write_io_threads = 4

# ======== 连接数 ========
max_connections = 200
max_allowed_packet = 64M

# ======== 查询缓存(MySQL 8.0 已移除) ========
# query_cache_type = 0                     # MariaDB 可用,MySQL 8.0 无效
# query_cache_size = 0

# ======== 临时表与排序 ========
tmp_table_size = 64M
max_heap_table_size = 64M
sort_buffer_size = 4M
join_buffer_size = 4M

# ======== 慢查询日志 ========
slow_query_log = ON
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 2

# ======== 二进制日志(用于复制) ========
# log_bin = /var/log/mysql/mysql-bin
# binlog_format = ROW
# expire_logs_days = 7

重启数据库:

sudo systemctl restart mariadb

验证配置:

-- 检查 InnoDB 配置
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
SHOW VARIABLES LIKE 'innodb_file_per_table';

-- 检查字符集
SHOW VARIABLES LIKE 'character_set_server';
SHOW VARIABLES LIKE 'collation_server';

4.3 PostgreSQL 配置

安装

# Ubuntu / Debian
sudo apt install -y postgresql postgresql-contrib

# 启动
sudo systemctl enable --now postgresql

创建数据库和用户

sudo -u postgres psql
-- 创建用户
CREATE USER ncuser WITH PASSWORD 'StrongPassword123!';

-- 创建数据库
CREATE DATABASE nextcloud
  OWNER ncuser
  ENCODING 'UTF8'
  LC_COLLATE = 'en_US.UTF-8'
  LC_CTYPE = 'en_US.UTF-8'
  TEMPLATE = template0;

-- 授权
GRANT ALL PRIVILEGES ON DATABASE nextcloud TO ncuser;

-- 启用扩展(可选)
\c nextcloud
CREATE EXTENSION IF NOT EXISTS pg_trgm;   -- 模糊搜索加速
\q

PostgreSQL 推荐配置

编辑 /etc/postgresql/15/main/postgresql.conf

# ======== 内存 ========
shared_buffers = 256MB                    # 总内存的 25%
effective_cache_size = 768MB              # 总内存的 75%
work_mem = 16MB
maintenance_work_mem = 128MB

# ======== WAL ========
wal_buffers = 16MB
checkpoint_completion_target = 0.9
max_wal_size = 1GB
min_wal_size = 256MB

# ======== 连接 ========
max_connections = 200

# ======== 查询优化 ========
random_page_cost = 1.1                    # SSD 设为 1.1,HDD 设为 4
effective_io_concurrency = 200            # SSD 设为 200
default_statistics_target = 100

# ======== 日志 ========
log_min_duration_statement = 2000         # 慢查询阈值(毫秒)
log_checkpoints = ON
log_connections = ON
log_disconnections = ON

# ======== JIT ========
jit = on
jit_above_cost = 100000

编辑 /etc/postgresql/15/main/pg_hba.conf 添加:

# 允许本地 Nextcloud 连接
local   nextcloud   ncuser                     md5
host    nextcloud   ncuser   127.0.0.1/32      md5
host    nextcloud   ncuser   ::1/128           md5
sudo systemctl restart postgresql

4.4 数据库迁移

SQLite → MySQL

# 1. 安装 MySQL 并创建数据库(见 4.2 节)

# 2. 导出 SQLite 数据
sudo -u www-data php /var/www/nextcloud/occ db:convert-type \
  --all-apps \
  mysql \
  ncuser \
  localhost \
  nextcloud

# 3. 确认迁移成功
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-columns
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-primary-keys

MySQL → PostgreSQL

# 1. 安装 PostgreSQL 并创建数据库

# 2. 使用 occ 迁移
sudo -u www-data php /var/www/nextcloud/occ db:convert-type \
  --all-apps \
  pgsql \
  ncuser \
  localhost \
  nextcloud

# 3. 验证
sudo -u www-data php /var/www/nextcloud/occ maintenance:repair

迁移注意事项

步骤操作说明
1开启维护模式occ maintenance:mode --on
2完整备份备份 data 目录 + 数据库 + config.php
3执行迁移occ db:convert-type
4修复数据库occ maintenance:repair
5关闭维护模式occ maintenance:mode --off
6验证功能登录、上传、分享等

4.5 数据库维护

日常维护命令

# 添加缺失的索引
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-indices

# 添加缺失的列
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-columns

# 添加缺失的主键
sudo -u www-data php /var/www/nextcloud/occ db:add-missing-primary-keys

# 转换字符集为 utf8mb4
sudo -u www-data php /var/www/nextcloud/occ db:convert-filecache-bigint

表优化

-- MySQL: 优化所有表
USE nextcloud;
SELECT CONCAT('OPTIMIZE TABLE `', TABLE_NAME, '`;')
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'nextcloud' AND ENGINE = 'InnoDB';

-- 批量执行优化
OPTIMIZE TABLE oc_filecache;
OPTIMIZE TABLE oc_activity;
OPTIMIZE TABLE oc_storages;
-- PostgreSQL: 清理与重建
VACUUM FULL ANALYZE;
REINDEX DATABASE nextcloud;

数据库状态监控

-- MySQL: 查看连接状态
SHOW STATUS LIKE 'Threads_connected';
SHOW STATUS LIKE 'Threads_running';
SHOW PROCESSLIST;

-- 查看 InnoDB 缓冲池命中率
SHOW STATUS LIKE 'Innodb_buffer_pool_read%';
-- 命中率 = 1 - (Innodb_buffer_pool_reads / Innodb_buffer_pool_read_requests)

-- PostgreSQL: 查看连接数
SELECT count(*) FROM pg_stat_activity;

-- 查看慢查询
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';

4.6 高可用与集群

MySQL 主从复制

┌──────────┐     binlog     ┌──────────┐
│  Master  │ ──────────────→│  Slave   │
│  (写入)  │                │  (只读)  │
└──────────┘                └──────────┘

Master 配置 (/etc/mysql/mariadb.conf.d/91-master.cnf):

[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin
binlog_format = ROW
expire_logs_days = 7

Slave 配置:

[mysqld]
server-id = 2
relay_log = /var/log/mysql/relay-bin
read_only = ON
-- Master: 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'ReplPassword!';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';

-- Slave: 配置主从关系
CHANGE MASTER TO
  MASTER_HOST='192.168.1.10',
  MASTER_USER='repl',
  MASTER_PASSWORD='ReplPassword!',
  MASTER_LOG_FILE='mysql-bin.000001',
  MASTER_LOG_POS=0;
START SLAVE;
SHOW SLAVE STATUS\G

注意: Nextcloud 目前不原生支持数据库读写分离。需要通过 ProxySQL 或 HAProxy 等中间件实现。

Galera Cluster(MariaDB)

┌──────────┐    ┌──────────┐    ┌──────────┐
│ Node 1   │◄──►│ Node 2   │◄──►│ Node 3   │
│ (读写)   │    │ (读写)   │    │ (读写)   │
└──────────┘    └──────────┘    └──────────┘

Galera 配置要点:

[mysqld]
wsrep_on = ON
wsrep_provider = /usr/lib/galera/libgalera_smm.so
wsrep_cluster_name = "nextcloud_cluster"
wsrep_cluster_address = "gcomm://192.168.1.10,192.168.1.11,192.168.1.12"
wsrep_node_address = "192.168.1.10"
wsrep_node_name = "node1"
wsrep_sst_method = rsync
binlog_format = ROW
default_storage_engine = InnoDB
innodb_autoinc_lock_mode = 2

4.7 数据库备份

MySQL 备份脚本

#!/bin/bash
# nextcloud-db-backup.sh

BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="nextcloud"
DB_USER="ncuser"
DB_PASS="StrongPassword123!"
RETENTION_DAYS=30

# 全量备份
mysqldump \
  --single-transaction \
  --routines \
  --triggers \
  --quick \
  --lock-tables=false \
  -u "$DB_USER" \
  -p"$DB_PASS" \
  "$DB_NAME" | gzip > "$BACKUP_DIR/nextcloud_${DATE}.sql.gz"

# 清理旧备份
find "$BACKUP_DIR" -name "nextcloud_*.sql.gz" -mtime +$RETENTION_DAYS -delete

echo "[$(date)] Backup completed: nextcloud_${DATE}.sql.gz"

PostgreSQL 备份脚本

#!/bin/bash
# nextcloud-pg-backup.sh

BACKUP_DIR="/backup/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)

# 使用 pg_dump 自定义格式(支持并行恢复)
pg_dump -U ncuser -Fc nextcloud > "$BACKUP_DIR/nextcloud_${DATE}.dump"

# 或 SQL 格式
pg_dump -U ncuser nextcloud | gzip > "$BACKUP_DIR/nextcloud_${DATE}.sql.gz"

# 清理 30 天前的备份
find "$BACKUP_DIR" -mtime +30 -delete

自动定时备份

# 添加 crontab
sudo crontab -e
# 每天凌晨 3:00 备份
0 3 * * * /usr/local/bin/nextcloud-db-backup.sh >> /var/log/nextcloud-backup.log 2>&1

4.8 注意事项

  1. utf8mb4: MySQL 必须使用 utf8mb4 字符集,否则 emoji 和部分中文会存储失败
  2. InnoDB: 必须使用 InnoDB 引擎,MyISAM 不支持事务和行级锁
  3. buffer_pool_size: InnoDB 缓冲池是 MySQL 最重要的性能参数,建议设为可用内存的 50-70%
  4. 连接数: 不要设置过大的 max_connections,PHP-FPM 进程数 × 数据库连接 = 总连接需求
  5. 定期优化: 每月对大表(如 oc_filecache)执行 OPTIMIZE TABLE
  6. 慢查询日志: 开启慢查询日志有助于发现性能瓶颈

4.9 扩展阅读


上一章: 03 - 配置详解 下一章: 05 - 存储方案 — 本地存储、对象存储与外部存储挂载。