nostr-rs-relay/docs/database-maintenance.md
github-actions[bot] 70da8eff42
Fork Sync: Update from parent repository (#5)
* docs: typo in `build-essential` package name

* improvement(NIP-42): use 'restricted:' prefix for auth error msgs

* docs: add database maintenance example queries

* feat: allow logging output to file

* feat: roll over logs daily

* refactor: reorder imports

* improvement: default to logging on stdout

* fix: ensure startup SQL runs, even with zero min writers

---------

Co-authored-by: thesimplekid <tsk@thesimplekid.com>
Co-authored-by: rorp <rorp@protonmail.com>
Co-authored-by: Yuval Adam <_@yuv.al>
Co-authored-by: Jamin M <jaminmenter@outlook.com>
Co-authored-by: Greg Heartsfield <scsibug@imap.cc>
2023-06-25 11:02:44 +02:00

4.0 KiB

Database Maintenance

nostr-rs-relay uses the SQLite embedded database to minimize dependencies and overall footprint of running a relay. If traffic is light, the relay should just run with very little need for intervention. For heavily trafficked relays, there are a number of steps that the operator may need to take to maintain performance and limit disk usage.

This maintenance guide is current as of version 0.8.2. Future versions may incorporate and automate some of these steps.

Backing Up the Database

To prevent data loss, the database should be backed up regularly. The recommended method is to use the sqlite3 command to perform an "Online Backup". This can be done while the relay is running, queries can still run and events will be persisted during the backup.

The following commands will perform a backup of the database to a dated file, and then compress to minimize size:

BACKUP_FILE=/var/backups/nostr/`date +%Y%m%d_%H%M`.db
sqlite3 -readonly /apps/nostr-relay/nostr.db ".backup $BACKUP_FILE"
sqlite3 $BACKUP_FILE "vacuum;"
bzip2 -9 $BACKUP_FILE

Nostr events are very compressible. Expect a compression ratio on the order of 4:1, resulting in a 75% space saving.

Vacuuming the Database

As the database is updated, it can become fragmented. Performing a full vacuum will rebuild the entire database file, and can reduce space. Running this may reduce the size of the database file, especially if a large amount of data was updated or deleted.

vacuum;

Clearing Hidden Events

When events are deleted, the event is not actually removed from the database. Instead, a flag HIDDEN is set to true for the event, which excludes it from search results. High volume replacements from profile or other replaceable events are deleted, not hidden, in the current version of the relay.

In the current version, removing hidden events should not result in significant space savings, but it can still be used if there is no desire to hold on to events that can never be re-broadcast.

PRAGMA foreign_keys = ON;
delete from event where HIDDEN=true;

Manually Removing Events

For a variety of reasons, an operator may wish to remove some events from the database. The only way of achieving this today is with manually run SQL commands.

It is recommended to have a good backup prior to manually running SQL commands!

In all cases, it is mandatory to enable foreign keys, and this must be done for every connection. Otherwise, you will likely orphan rows in the tag table.

Deleting Specific Event

PRAGMA foreign_keys = ON;
delete from event where event_hash=x'00000000000c1271675dc86e3e1dd1336827bccabb90dc4c9d3b4465efefe00e';

Querying and Deleting All Events for Pubkey

PRAGMA foreign_keys = ON;

select lower(hex(author)) as author, count(*) as c from event group by author order by c asc;

delete from event where author=x'000000000002c7831d9c5a99f183afc2813a6f69a16edda7f6fc0ed8110566e6';

Querying and Deleting All Events of a Kind

PRAGMA foreign_keys = ON;

select printf('%7d', kind), count(*) as c from event group by kind order by c;

delete from event where kind=70202;

Deleting Old Events

In this scenario, we wish to delete any event that has been stored by our relay for more than 1 month. Crucially, this is based on when the event was stored, not when the event says it was created. If an event has a created field of 2 years ago, but was first sent to our relay yesterday, it would not be deleted in this scenario. Keep in mind, we do not track anything for re-broadcast events that we already have, so this is not a very effective way of implementing a "least recently seen" policy.

PRAGMA foreign_keys = ON;
TODO!

Delete Profile Events with No Recent Events

Many users create profiles, post a "hello world" event, and then never appear again (likely using an ephemeral keypair that was lost in the browser cache). We can find these accounts and remove them after some time.

PRAGMA foreign_keys = ON;
TODO!