上一篇 下一篇 分享链接 返回 返回顶部

数据库迁移至美国NVMe服务器前,如何检查容量、备份与写入监控?

发布人:Minchunlin 发布时间:2026-09-28 16:10 阅读量:13
数据库迁移至美国NVMe服务器前,如何检查容量、备份与写入监控?

把数据库迁移到美国NVMe服务器前,先不要急着复制数据。美国NVMe服务器提升数据库性能的前提,是目标端容量足够、备份可以恢复、写入量能够被持续观察,并且切换失败时仍能回到源端。NVMe只改善存储路径,不能弥补磁盘空间不足、备份不可用、事务日志堆积或查询与锁竞争。

最小可用方案可以先满足六项条件:确认数据库版本和数据目录、盘点真实容量、完成一次可验证的备份、在目标端完成隔离恢复、建立写入监控、制定不丢数据的回滚边界。读写分离、持续复制、独立备份盘和可视化监控可以后续增加,不必在第一次迁移中全部引入。

先明确迁移前的最低条件

检查项目必须确认的内容不满足时的处理
数据库版本源端和目标端的数据库主版本、扩展、字符集和时区先在隔离环境完成兼容性测试,不要直接跨大版本恢复
数据容量数据、索引、临时文件、事务日志或二进制日志的实际占用重新计算目标端所需空间,不能只按业务表大小估算
备份备份文件完整,能够在隔离数据库中恢复备份未验证前,不进行正式切换
写入量业务高峰和低峰的写入变化、日志增长和磁盘写入先建立基线,再决定维护窗口或是否需要复制方案
目标环境数据目录挂载点、文件系统、数据库用户、应用连接参数目标端先完成基础部署和权限检查
回滚条件切换前谁是权威数据源,切换后哪些写入可以回退不明确时不要让目标端直接承接生产写入

如果无法取得至少一个业务高峰和低峰的数据,容量与写入判断只能作为估算,不能据此承诺具体承载量。迁移前应优先记录源端的数据库大小、磁盘使用率、写入日志增长、数据库连接数和备份文件大小。

一、先检查容量,而不是只看数据库表大小

1. 找到真实的数据目录和挂载点

先确认数据库版本与数据目录。下面以Linux服务器为例,路径需要替换为实际目录:

psql --version
sudo -u postgres psql -Atc "SELECT version();"
sudo -u postgres psql -Atc "SHOW data_directory;"

如果使用MySQL或兼容实现,应先确认版本和数据目录:

mysql --version
mysql -NBe "SELECT VERSION();"
mysql -NBe "SELECT @@datadir;"

确认路径后,再检查文件系统。不要把示例路径直接当成生产路径:

DATA_DIR=/var/lib/postgresql
df -hT "$DATA_DIR"
df -ih "$DATA_DIR"
findmnt -T "$DATA_DIR"
lsblk -f

需要同时关注以下项目:

  • df -hT:容量、已用空间、可用空间和文件系统类型。
  • df -ih:inode是否耗尽。大量小文件、日志或临时文件可能先耗尽inode。
  • findmnt:确认数据目录是否真的位于预期挂载点,避免数据写到了系统盘。
  • lsblk -f:确认设备、文件系统和挂载关系,不能只看设备名称判断是否使用了目标存储。

如果系统安装了GNU版磁盘工具,可以进一步查看目录占用:

du -xhd1 "$DATA_DIR" 2>/dev/null | sort -h

不要只统计数据库主目录。还应检查备份目录、系统日志目录、临时目录和应用日志目录。如果迁移备份文件也存放在目标服务器,备份文件必须纳入目标盘容量计算。

2. 获取数据库内部的实际大小

PostgreSQL可以按数据库查看数据和索引总量:

SELECT
    datname,
    pg_size_pretty(pg_database_size(datname)) AS database_size,
    pg_database_size(datname) AS database_size_bytes
FROM pg_database
WHERE datistemplate = false
ORDER BY pg_database_size(datname) DESC;

如需定位单个数据库中最大的表和索引,可在目标数据库或源数据库中执行:

SELECT
    n.nspname AS schema_name,
    c.relname AS object_name,
    pg_size_pretty(pg_total_relation_size(c.oid)) AS total_size,
    pg_total_relation_size(c.oid) AS total_size_bytes
FROM pg_class AS c
JOIN pg_namespace AS n ON n.oid = c.relnamespace
WHERE c.relkind IN ('r', 'm', 'p')
ORDER BY pg_total_relation_size(c.oid) DESC
LIMIT 20;

MySQL可以先查看各库的表数据和索引大小:

SELECT
    table_schema,
    ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb
FROM information_schema.tables
GROUP BY table_schema
ORDER BY SUM(data_length + index_length) DESC;

数据库统计值与文件系统占用不一定完全相同。文件系统还可能包含事务日志、临时表、归档日志、错误日志、已删除但仍被进程占用的文件,以及恢复过程中的临时文件。因此,目标端所需空间应按下面的思路计算:

目标端最低所需空间
= 数据与索引实际占用
+ 恢复或重建索引所需临时空间
+ 备份或导出文件占用(如果放在目标端)
+ 迁移期间保留的WAL或二进制日志
+ 操作系统和数据库日志空间
+ 计划增长预留

如果采用逻辑备份,目标端在恢复期间可能同时存在导入文件、已恢复的数据、索引构建临时文件和日志。压缩后的备份文件大小不能直接等同于恢复后的数据库大小,必须以实际恢复测试中的峰值占用为准。

3. 用“可用空间”而不是“总容量”做判断

以下情况说明目标端容量不足或规划过于紧张:

  • 目标端只有刚好容纳当前数据的空间,没有备份和恢复临时空间。
  • WAL、二进制日志或临时文件增长后,可用空间快速下降。
  • 数据库数据目录和备份目录共用同一文件系统。
  • inode剩余很少,即使容量还有空余也可能无法创建新文件。
  • 恢复过程中出现“no space left on device”或临时目录写入失败。
  • 迁移必须删除旧备份才能腾出空间。

遇到这些情况,不应手动删除数据库目录中的文件、WAL文件或二进制日志来“临时腾空间”。正确做法是停止恢复或暂停切换,确认哪些日志受数据库管理,再通过数据库自身的保留策略或增加可用空间处理。

二、备份必须验证“能恢复”,不能只验证“文件存在”

1. 选择最小可用的备份方式

对单次迁移、能够接受维护窗口的场景,逻辑备份通常更容易核对和回滚。下面以PostgreSQL为例:

export APP_DB=appdb
export BACKUP_FILE=/backup/db-migration/appdb.dump

pg_dump \
  --format=custom \
  --no-owner \
  --no-acl \
  --file="$BACKUP_FILE" \
  "$APP_DB"

test -s "$BACKUP_FILE"
sha256sum "$BACKUP_FILE"
pg_restore --list "$BACKUP_FILE" > "${BACKUP_FILE}.list"

执行前应确认备份目录有足够空间,并使用安全的数据库认证方式,不要把数据库密码直接写在命令行或脚本中。pg_dump完成不代表恢复一定成功,pg_restore --list只能确认备份目录可读,还需要实际恢复测试。

MySQL或兼容实现可以使用一致性导出作为最小方案:

export APP_DB=appdb
export BACKUP_FILE=/backup/db-migration/appdb.sql

mysqldump \
  --single-transaction \
  --routines \
  --events \
  --triggers \
  --hex-blob \
  "$APP_DB" > "$BACKUP_FILE"

test -s "$BACKUP_FILE"
sha256sum "$BACKUP_FILE"

--single-transaction主要适用于事务型表。若数据库中存在非事务型表、特殊存储引擎或需要锁定才能保证一致性的对象,应先确认导出一致性,不能把该参数当作所有表的通用保证。

2. 在目标端进行隔离恢复

恢复测试必须使用目标端的独立数据库名或隔离实例,不能直接覆盖待切换的生产数据库。恢复会写入大量数据,操作前应确认目标端有足够空间,并保留源端原始数据和备份文件。

PostgreSQL示例:

export RESTORE_DB=appdb_restore_check

createdb -T template0 "$RESTORE_DB"

pg_restore \
  --exit-on-error \
  --no-owner \
  --no-acl \
  --dbname="$RESTORE_DB" \
  "$BACKUP_FILE"

psql "$RESTORE_DB" -c "SELECT current_database(), version();"
psql "$RESTORE_DB" -c "SELECT extname FROM pg_extension ORDER BY extname;"

createdb和pg_restore属于数据库写入操作,只能对确认为空的隔离数据库执行。不要把RESTORE_DB替换成仍在提供生产流量的数据库名。若恢复失败,应保留错误日志,删除或重建隔离数据库前先确认不需要其中的数据,不要用批量删除命令处理生产目录。

MySQL示例:

export RESTORE_DB=appdb_restore_check

mysql -e "CREATE DATABASE \`$RESTORE_DB\`;"
mysql "$RESTORE_DB" < "$BACKUP_FILE"
mysql "$RESTORE_DB" -e "SELECT DATABASE(), VERSION();"

上面的建库和导入操作同样只适用于新建的隔离数据库。若数据库已存在,不应直接导入,否则可能覆盖同名对象或造成对象混杂。

3. 验证恢复结果

恢复成功至少要核对四类结果:

  1. 对象是否完整:数据库、表、索引、视图、存储过程、触发器、扩展和权限是否符合源端清单。
  2. 数据是否完整:抽查核心表的记录数、最大主键、最新业务时间和关键状态分布。
  3. 连接是否正常:使用生产应用账号进行连接测试,检查字符集、时区和默认Schema。
  4. 写入是否正常:在隔离环境使用应用的测试流程执行一次新增、修改和事务回滚验证。

不要只比较所有表的记录总数。记录数相同不代表数据内容一致,至少应对核心业务表进行抽样校验。对于有序列、自增字段或特殊权限的数据库,还要验证新数据能够继续写入。

如果恢复测试出现以下问题,应在隔离环境修复后再进入迁移窗口:

现象常见原因处理方向
找不到扩展或插件目标端未安装对应扩展,或版本不兼容先完成扩展安装和版本匹配
恢复时权限错误目标端角色、所有者或授权关系不同根据最小权限原则补齐角色和授权
字符集或排序规则异常源端与目标端默认设置不同显式设置数据库字符集、排序规则和连接参数
恢复中途空间不足只按备份文件大小估算容量记录峰值占用,重新规划目标存储
导入成功但应用报错连接参数、时区、Schema或序列未匹配使用应用账号进行完整冒烟测试

三、迁移前建立写入监控基线

1. 先看操作系统层面的写入

如果系统已安装sysstat,可以使用以下命令观察磁盘写入:

iostat -xz 1

重点观察目标数据盘对应设备的:

  • 写入吞吐量;
  • 写请求数量;
  • await或写入等待时间;
  • 设备利用率;
  • 队列长度;
  • 是否出现持续的写入等待。

同时可以查看进程级磁盘活动:

pidstat -d 1

如果命令不存在,应先确认发行版和软件包来源,再安装监控工具,不要在正式切换高峰临时修改生产环境。iostat字段名称可能随工具版本不同而变化,判断时应以实际输出的字段说明为准。

文件系统空间建议与写入监控同时执行:

watch -n 5 'df -hT /var/lib/postgresql; df -ih /var/lib/postgresql'

将路径替换为实际数据目录。如果不确定数据库进程名称或数据盘设备,不要凭进程名猜测,应结合psql、mysql返回的数据目录和findmnt结果确认。

2. 查看数据库内部的累计写入计数

PostgreSQL中的许多统计项是从统计重置后开始累计的,需要连续采样并计算两个时间点之间的差值:

SELECT
    now(),
    datname,
    xact_commit,
    xact_rollback,
    tup_inserted,
    tup_updated,
    tup_deleted,
    temp_files,
    temp_bytes
FROM pg_stat_database
WHERE datname IS NOT NULL;

如果数据库版本提供WAL统计,可以查看WAL记录和字节变化:

SELECT
    now(),
    wal_records,
    wal_fpi,
    wal_bytes
FROM pg_stat_wal;

如果当前版本不支持某个列,应先执行以下命令确认版本和可用字段,不要直接套用其他版本的查询:

SELECT version();
\d+ pg_stat_wal

也可以在psql中连续观察:

SELECT
    now(),
    datname,
    xact_commit,
    xact_rollback,
    tup_inserted,
    tup_updated,
    tup_deleted,
    temp_bytes
FROM pg_stat_database
WHERE datname = 'appdb';
\watch 5

xact_commit、tup_inserted等是累计值,不能把某一次输出直接当作每秒写入量。应记录一段时间内的增量,并分别保存业务低峰、高峰和备份期间的结果。

MySQL可以查询InnoDB日志和数据写入相关计数:

SHOW GLOBAL STATUS
WHERE Variable_name IN (
    'Innodb_os_log_written',
    'Innodb_data_written',
    'Innodb_log_waits',
    'Com_insert',
    'Com_update',
    'Com_delete',
    'Threads_connected'
);

其中,Innodb_os_log_written、Innodb_data_written和各类Com_计数通常也是累计值。两次采样的差值可以用来判断写入趋势。Innodb_log_waits持续增加,通常说明日志缓冲或存储写入跟不上事务产生速度,需要结合磁盘等待、日志配置和事务大小继续判断。

3. 采用基线对比,不要只看单个指标

观察结果可能说明下一步
数据库写入计数突然增加,磁盘写入同步增加业务批处理、导入任务或定时任务正在运行确认任务时间,避免在异常高峰切换
WAL或二进制日志增长,但业务写入没有明显增加复制、归档、长事务或日志保留异常检查长事务、归档状态和日志保留规则
磁盘等待升高,CPU利用率不高存储队列、文件系统或后台任务可能成为瓶颈分离备份任务,检查数据盘和日志盘的写入
可用空间持续下降数据增长、日志积压、临时文件或备份占用空间先查明增长来源,不要手动删除数据库日志
写入量不高但应用仍然变慢瓶颈可能在锁、CPU、查询计划或连接池不要仅凭NVMe更换判断数据库一定会变快
迁移恢复阶段写入远高于日常基线索引构建、批量导入或日志刷盘正在集中发生延长维护窗口,重新确认目标端容量和写入承受能力

写入监控的目的不是追求某个固定数字,而是发现迁移期间是否偏离源端基线。不同数据库版本、表结构、事务大小和索引数量都会改变写放大,不能用单一的每秒写入量推导所有业务的安全值。

四、按最小方案执行正式迁移

如果业务可以接受维护窗口,可以采用“最终停写、最终备份、目标端恢复、验证后切换”的路径。它比实时复制简单,但维护时间取决于备份和恢复速度,必须先做一次恢复演练。

第一步:冻结变更并确认源端状态

在维护窗口开始前:

  • 停止定时导入、批处理和会修改数据库的后台任务;
  • 记录源端数据库版本、数据目录、空间使用率和写入基线;
  • 确认目标端的数据库服务、挂载点和监控已正常工作;
  • 确认备份目录有足够空间,备份文件不会与源端共用唯一存储;
  • 保留源端,不要提前卸载数据盘或删除数据库文件。

第二步:停止应用写入,再生成最终备份

先让应用进入维护状态或只读状态,再确认没有新的写事务进入。可以通过应用层连接控制和数据库活动查询双重确认。不要只关闭一个应用进程,因为定时任务、管理脚本或其他服务可能仍在写入。

完成最终备份后,立即执行文件大小、校验和和备份目录清单检查。最终备份必须标记时间和来源,避免误用演练备份。

第三步:在目标端恢复并观察空间

恢复过程中同时观察:

df -hT /目标数据目录
df -ih /目标数据目录
iostat -xz 1

将/目标数据目录替换成目标服务器真实路径。恢复过程中如果空间快速下降、日志持续增长或设备等待异常,应暂停后续切换,先确认是否仍有临时文件、旧备份或索引构建过程占用空间。

第四步:完成数据和应用验证

验证内容至少包括:

  • 核心表记录数和关键时间范围;
  • 数据库版本、扩展、字符集、时区和默认Schema;
  • 应用账号连接;
  • 查询、登录、下单或其他核心业务流程;
  • 一次受控的写入和事务回滚测试;
  • 目标端写入监控是否有异常增长。

如果验证失败,源端仍未承接新写入时,可以直接放弃目标端本次恢复,修复原因后重来。不要为了赶时间跳过验证。

第五步:切换连接并观察目标端写入

切换应用连接参数或内部服务地址后,先观察少量业务请求,再逐步恢复正常流量。切换后重点观察:

  • 目标数据库是否出现连接失败;
  • 写入计数是否与业务流量匹配;
  • WAL或二进制日志是否持续堆积;
  • 数据盘可用空间是否异常下降;
  • 应用错误日志和事务回滚是否增加;
  • 写入等待是否明显偏离迁移前基线。

如果目标端写入正常、关键业务验证通过,并且监控在一段观察窗口内稳定,再结束源端的只读保留期。源端不要在刚切换成功后立即删除,至少应按照既定保留策略保存回退条件和原始备份。

五、失败回滚时要区分“尚未写入”和“已经写入”

切换后目标端还没有生产写入

如果应用尚未向目标端写入,且只是连接、权限或应用启动失败,可以:

  1. 停止目标端对外提供生产写入;
  2. 将应用连接恢复到源端;
  3. 验证源端仍可读写;
  4. 记录目标端失败原因;
  5. 修复目标配置后重新演练。

这种回滚相对简单,因为源端仍然是最新数据源。

目标端已经产生生产写入

如果目标端已经接受了新增、修改或删除,不能直接把连接切回源端。这样会丢失目标端的新数据,形成双写分叉。此时应先停止写入,保留目标端现场,根据实际情况选择:

  • 导出目标端新增或变更数据,再经过校验后合并到源端;
  • 使用预先建立的反向复制或增量同步方案;
  • 从目标端备份恢复到新的隔离环境后进行数据比对;
  • 如果无法安全合并,则暂停回滚,由数据库管理员制定数据修复方案。

因此,回滚方案必须在切换前写清楚“最后一致时间”和“谁是当前权威库”,而不是只准备一个旧连接地址。

六、什么时候需要升级迁移方案

最小方案适合数据规模可控、能够安排维护窗口、应用可以短时间停止写入的场景。出现以下情况时,应在正式迁移前增加资源或改用更完整的同步方式:

  • 最终备份和恢复时间超过可接受维护窗口;
  • 源端在备份期间仍必须持续写入;
  • 目标端恢复测试中的峰值空间无法满足;
  • WAL或二进制日志在业务高峰持续增长,且没有可靠保留空间;
  • 只能通过删除旧备份、日志或数据库文件来腾出空间;
  • 迁移后写入等待长期高于源端基线;
  • 业务要求切换失败后能够保留目标端新写入并快速回退;
  • 当前只能人工查看命令输出,无法持续记录空间、写入和备份状态。

升级方向可以按实际缺口选择:为备份和数据库数据使用独立存储、增加持续日志归档、建立增量或实时复制、接入集中式监控、延长观察窗口,或先优化高写入任务和长事务。

只要容量检查、可恢复备份、写入基线和回滚边界都能通过验证,迁移到美国NVMe服务器就有了可判断的基础。若其中任何一项无法验证,优先解决验证问题,而不是仅凭NVMe存储介质推断数据库一定会获得性能提升。

目录结构
全文