This document describes the process of migrating LND
's database state from one
type of database backend (for example the bbolt
based database files *.db
such as the channel.db
or wallet.db
files) to another (for example the new
postgres
or sqlite
databases introduced in lnd v0.14.0-beta
).
Note: Currently only migrations from bolt
to either postgres
or
sqlite
are supported. KV based databases will be phased out in the future. We
are planning to add additonal support to migrate all etcd
databases to sql
databases. Moreover it is currently also not supported to move the database
from sqlite
to postgres
or vice versa, because this migration only takes
care of the key value data and there already exist the possiblity to have the
invoices in native sql which this tool does not support.
To be able to execute the migration successfully you have to update to LND v0.19.0 which makes sure that the intial pre-migration state of the kv-db is up to date.
Prepare a user and database as described in the Postgres
documentation. You'll need the Data Source Name (DSN) for both the data
migration and then the lnd
configuration, so keep that string somewhere
(should be something with the format of postgres://xx:yy@localhost:5432/zz
).
No additional steps are required to prepare the Postgres database for the data migration. The migration tool will create the database schema automatically, so no DDL scripts need to be run in advance. But to speed up the migration process you should take a look at the following postgres server tuning guide
No particular preparation is needed for sqlite
compared to the postgres
case. Similar to the bolt
case there will be separated db files created for
each individual bolt
database.
Assuming we want to migrate the database state from the pre-0.19.0 individual
bbolt
based *.db
files to a remote database, we first need to make sure the
source files are in the correct state.
The following steps should be performed before running the data migration ( some of them are marked as optional and can be neglected for small databases e.g. 200MB ):
- Stop
lnd
- Upgrade the
lnd
binary to the latest version (e.g.v0.19.0-beta
or later) - (optional) Make sure to add config options like
gc-canceled-invoices-on-startup=true
anddb.bolt.auto-compact=true
to yourlnd.conf
to optimize the source database size by removing canceled invoices and compacting it on startup. - Remove any data from the source database that you can. The fewer
entries are in the source database, the quicker the migration will complete.
For example failed payments (or their failed HTLC attempts) can be removed
with
lncli deletepayments --all
. This can make a huge difference for routing nodes which rebalance a lot. Make sure you restart LND and compact the db after the failed payments were deleted so it has an effect on the size of the db. - (optional) Also make sure to migrate the revocation log for all channels
active prior to
[email protected]
by activating the config setting--db.prune-revocation
. This version introduced an optimized revocation log storage system that reduces the storage footprint. All channels will be automatically migrated to this new format when the setting is enabled. - Start
lnd
normally, using the flags mentioned above but not yet changing any database backend related configuration options. Check the log that the database schema was migrated successfully, for example:Checking for schema update: latest_version=XX, db_version=XX
. This relates to the kv-schema NOT any SQL schema, this makes sure all inital migration of the old database were performed. This migration tool is only allowed for DBs which have all the latest db migrations applied up to LND 19. This makes sure that all LND nodes which want to migrate to the SQL world have the latest db modifications in place before migrating to a different DB type. If that is not the case the migration will be refused. - Stop
lnd
again and make sure it isn't started again by accident during the data migration (e.g. disable anysystemd
or other scripts that start/stoplnd
).
Depending on the destination database type, run the migration with a command similar to one of the following examples:
Example: Migrate from bbolt
to sqlite
:
lndinit --debuglevel info migrate-db \
--source.bolt.data-dir /home/myuser/.lnd/data \
--dest.backend sqlite \
--dest.sqlite.data-dir /home/myuser/.lnd/data --network mainnet
If you were running a watchtower server, and it had a different directory set
compared to the default LND
directory make sure you also add the tower dir
setting. It has to be the directory to the watchtower
dir, excluding the
watchtower
name e.g.:
--source.bolt.tower-dir /home/myuser/towerdir
.
Example: Migrate from bbolt
to postgres
:
lndinit --debuglevel info migrate-db \
--source.bolt.data-dir /home/myuser/.lnd/data \
--dest.backend postgres \
--dest.postgres.dsn=postgres://postgres:postgres@localhost:5432/postgres
Also set the watchtower directory in case you used a different path, see above.
This migration tool depends on the directory structure of
the LND software. This means make sure you link the correct folder because the
bolt
database has several database files in serveral subfolders. This
migration tool will make sure that all the required databases are migrated. It
will not require a wtclient.db
or a watchtower.db
.
The migration is resumable and happens in chunks of default 20MB to make it
compatible with most of the systems including low power devices like
raspberry pis. However if you have better setup with way more RAM feel free to
increase the --chunk-size
to something like
200MB which should speed up the migration. You can also change the chunk size
during the migration as well. If you want to start the migration from the
beginning (can only be done if the migration did still not succeed) use the
flag --force-new-migration
which can be used in combination with a
new chunksize
limit.
In case you have successfully migrated several nodes and are not sure anymore
which source db corresponds to which destination db there is a flag called
force-verify-db
which only works if both dbs are marked as successfully
migrated. It will verify the contents of the db.
Make sure the whole migration process succeeds before starting the new node with the new underlying database. As mentioned above there are several database files at play here so all of them have to succeed to garantee a successful migration.
If the migration succeeded successfully and you see the following log entry of the migration tool you are good to go to start-up your lnd node with the new database.
[INF]: LNDINIT !!!Migration of all mandatory db parts completed successfully!!!
The mandatory dbs are:
channel.db
macaroons.db
sphinxreplay.db
wallet.db
The optional dbs are:
wtclient.db
watchtower.db
neutrino.db
[db]
db.backend=sqlite
There are several other sqlite setttings you can tweak to make it fit your needs, take a look at the lnd-sample-config.
[db]
db.backend=postgres
[postgres]
db.postgres.dsn=postgres://xx:yy@localhost:5432/zz
Use the same connection string you used for the migration. Also take a look at the postgres knobs in the lnd-sample-config.
This is the output of the migration cmd help settings:
lndinit migrate-db -h
Usage:
lndinit [OPTIONS] migrate-db [migrate-db-OPTIONS]
Migrate the full database state of lnd from a source (for example the
set of bolt database files such as channel.db and wallet.db) database
to a SQL destination database.
IMPORTANT: Please read the data migration guide located in the file
docs/data-migration.md of the main lnd repository before using this
command!
NOTE: The migration can take a long time depending on the amount of data
that needs to be written! The migration happens in chunks therefore it
can be resumed in case of an interruption. The migration also includes
a verification to assure that the migration is consistent.
As long as NEITHER the source nor destination database has been started/
run with lnd, the migration can be repeated/resumed in case of an error
since the data will just be overwritten again in the destination.
Once a database was successfully and completely migrated from the source
to the destination, the source will be marked with a 'tombstone' tag
while the destination will get an 'already migrated' tag.
A database with a tombstone cannot be started with lnd anymore to
prevent from an old state being used by accident.
To prevent overwriting a destination database by accident, the same
database/namespace pair cannot be used as the target of a data migration
twice, which is checked through the 'already migrated' tag.
Application Options:
-e, --error-on-existing Exit with code EXIT_CODE_TARGET_EXISTS (128) instead of 0 if the result of an action is already present
-d, --debuglevel= Set the log level (Off, Critical, Error, Warn, Info, Debug, Trace)
Help Options:
-h, --help Show this help message
[migrate-db command options]
-n, --network= Network of the db files to migrate (used to navigate into the right directory) (default: mainnet)
--pprof-port= Enable pprof profiling on the specified port
--force-new-migration Force a new migration from the beginning of the source DB so the resume state will be discarded
--force-verify-db Force a verification verifies two already marked (tombstoned and already migrated) dbs to make sure that the source db equals the
content of the destination db
--chunk-size= Chunk size for the migration in bytes
source:
--source.backend=[bolt] The source database backend. (default: bolt)
bolt:
--source.bolt.dbtimeout= Specify the timeout value used when opening the database. (default: 1m0s)
--source.bolt.data-dir= Lnd data dir where bolt dbs are located.
--source.bolt.tower-dir= Lnd watchtower dir where bolt dbs for the watchtower server are located.
dest:
--dest.backend=[postgres|sqlite] The destination database backend. (default: postgres)
postgres:
--dest.postgres.dsn= Database connection string.
--dest.postgres.timeout= Database connection timeout. Set to zero to disable.
--dest.postgres.maxconnections= The maximum number of open connections to the database. Set to zero for unlimited.
sqlite:
--dest.sqlite.data-dir= Lnd data dir where sqlite dbs are located.
--dest.sqlite.tower-dir= Lnd watchtower dir where sqlite dbs for the watchtower server are located.
sqlite-config:
--dest.sqlite.sqlite-config.timeout= The time after which a database query should be timed out.
--dest.sqlite.sqlite-config.busytimeout= The maximum amount of time to wait for a database connection to become available for a query.
--dest.sqlite.sqlite-config.maxconnections= The maximum number of open connections to the database. Set to zero for unlimited.
--dest.sqlite.sqlite-config.pragmaoptions= A list of pragma options to set on a database connection. For example, 'auto_vacuum=incremental'. Note that the flag must be specified multiple times if multiple options are to be set.