给区块数据单独挂一块盘:blocksdir 拆开时哪些文件跟着走、哪些留在原地 图 1
给区块数据单独挂一块盘:blocksdir 拆开时哪些文件跟着走、哪些留在原地 · 图 1

全节点的硬盘上最重的东西是区块数据:主网的 blk 文件早已长到数百 GB 量级,而链状态数据库、钱包、配置加起来只占小头。把大盘机装不进节点盘的矛盾交给参数来解决,就是 -blocksdir。它的帮助文本一句话:“为 *.dat 文件指定用于存放 blocks 子目录的目录(默认:<datadir>)“。本文基于 Bitcoin Core 31.0 源码,讲清楚这个参数拆开的到底是哪一块、搬走之后哪些东西留在原地。

参数定位的是一层”容器目录”

容易误解的第一点:-blocksdir 指向的不是 blk 文件本身所在的目录,而是容器。源码里计算区块目录的路径函数把参数值转成绝对路径后,还要再拼接网络子目录和 blocks 一层:主网最终是”指定目录下的 blocks 子目录”,测网与签网则各自带一个网络名子目录。这与数据目录内部的布局完全同构,帮助文本说的”用于存放 blocks 子目录的目录”就是这个意思。第二点:容器目录必须提前存在。初始化阶段先做存在性检查,目录不存在直接以”指定的 blocks 目录不存在”报错停机;而里面的 blocks 子目录会由节点自动创建。迁移时先建目录再启动,是最常见的第一步。

给区块数据单独挂一块盘:blocksdir 拆开时哪些文件跟着走、哪些留在原地 图 2
给区块数据单独挂一块盘:blocksdir 拆开时哪些文件跟着走、哪些留在原地 · 图 2

跟着搬走的东西

搬动或改指容器后,真正被读写进这个位置的是:区块文件 blk 与撤销数据 rev(同一批平铺文件,修剪节点删旧文件也发生在新目录里)、混淆密钥文件 xor.dat,以及自动创建的 blocks 子目录本身。混淆密钥值得多说一句:它放在区块目录内,节点启动时若发现密钥文件已存在则优先读取,写盘读盘都用它做异或混淆;如果目录是全新的——判据是目录里只有以点开头的隐藏类文件,连文件锁都算在内——才会生成随机密钥。这解释了一个迁移坑:只搬 blk 和 rev 而漏掉 xor.dat,节点会在新位置以零密钥起步,旧文件的字节无法按正确密钥还原,读块将按损坏处理。另外,如果曾用随机密钥写过数据、后来想以关闭混淆(-blocksxor=0)的方式指向同一个目录,源码会直接报错停机等人工干预,不允许带着旧密钥装作没看见。

留在数据目录的东西

区块相关的东西并非全跟 -blocksdir 走。区块索引数据库位于数据目录下的 blocks 子目录里的 index——它不随容器搬走;链状态(UTXO 集合数据库)、钱包目录、对等地址表、费用估计文件、配置与日志,全部与这个参数无关。这种”数据文件与索引分居两处”的设计意味着:改了 -blocksdir 而旧目录里的文件没搬齐时,节点拿着索引去新位置找文件会找不着,正常无法继续同步,通常需要用重建索引的方式恢复。所以稳妥的迁移顺序是:完整关停节点,在目标盘创建容器目录,把旧 blocks 目录的内容整体移动过去(包含混淆密钥文件),带参数启动并确认区块高度能继续增长,最后才清理旧位置。

与修剪、多网络共存的注意点

开了修剪的节点搬完目录后,删除旧块文件的行为在新位置照常发生,不需要额外参数;多网络共用一块大盘时更推荐用好它自带的网络子目录结构,同一份配置换网络启动时各网络数据自然分层,不会互相踩。还有一个测试向的伙伴参数 -fastprune,用更小的区块文件和更低的修剪高度做快速测试,与容器目录参数配合能把测试数据隔离在独立盘上,但它属于调试类选项,不进常规帮助输出。

风险提示:本文全部路径与行为描述基于 Bitcoin Core 31.0 源码,目录结构随版本可能演进,以你实际运行版本为准。区块数据搬移涉及节点可用性中断与磁盘空间规划,操作前请确认备份与回滚方案;本文不构成任何投资建议。