mirror of
https://github.com/uprightbass360/AzerothCore-RealmMaster.git
synced 2026-02-03 10:53:48 +00:00
feat: upgrade
This commit is contained in:
@@ -181,16 +181,20 @@ The system automatically detects and restores backups on first startup:
|
||||
|
||||
### Restore Safety Checks & Sentinels
|
||||
|
||||
Because MySQL stores its hot data in a tmpfs (`/var/lib/mysql-runtime`) while persisting only backups and status markers under `local-storage/mysql-data`, it is possible for the runtime data to be wiped (for example, after a host reboot) while the sentinel `.restore-completed` file still claims the databases are ready. To prevent the worldserver and authserver from entering restart loops, the `ac-db-import` workflow now performs an explicit sanity check before trusting those markers:
|
||||
Because MySQL stores its hot data in a tmpfs (`/var/lib/mysql-runtime`) while persisting the durable files inside the Docker volume `mysql-data` (mounted at `/var/lib/mysql-persistent`), it is possible for the runtime data to be wiped (for example, after a host reboot) while the sentinel `.restore-completed` file still claims the databases are ready. To prevent the worldserver and authserver from entering restart loops, the `ac-db-import` workflow now performs an explicit sanity check before trusting those markers:
|
||||
|
||||
- The import script queries MySQL for the combined table count across `acore_auth`, `acore_world`, and `acore_characters`.
|
||||
- If **any tables exist**, the script logs `Backup restoration completed successfully` and skips the expensive restore just as before.
|
||||
- If **no tables are found or the query fails**, the script logs `Restoration marker found, but databases are empty - forcing re-import`, automatically clears the stale marker, and reruns the backup restore + `dbimport` pipeline so services always start with real data.
|
||||
|
||||
To complement that one-shot safety net, the long-running `ac-db-guard` service now watches the runtime tmpfs. It polls MySQL, and if it ever finds those schemas empty (the usual symptom after a daemon restart), it automatically reruns `db-import-conditional.sh` to rehydrate from the most recent backup before marking itself healthy. All auth/world services now depend on `ac-db-guard`'s health check, guaranteeing that AzerothCore never boots without real tables in memory. The guard also mounts the working SQL tree from `local-storage/source/azerothcore-playerbots/data/sql` into the db containers so that every `dbimport` run uses the exact SQL that matches your checked-out source, even if the Docker image was built earlier.
|
||||
|
||||
Because new features sometimes require schema changes even when the databases already contain data, `ac-db-guard` now performs a `dbimport` verification sweep (configurable via `DB_GUARD_VERIFY_INTERVAL_SECONDS`) to proactively apply any outstanding updates from the mounted SQL tree. By default it runs once per bootstrap and then every 24 hours, so the auth/world servers always see the columns/tables expected by their binaries without anyone having to run host scripts manually.
|
||||
|
||||
Manual intervention is only required if you intentionally want to force a fresh import despite having data. In that scenario:
|
||||
|
||||
1. Stop the stack: `docker compose down`
|
||||
2. Delete the sentinel: `rm -f local-storage/mysql-data/.restore-completed`
|
||||
2. Delete the sentinel inside the volume: `docker run --rm -v mysql-data:/var/lib/mysql-persistent alpine sh -c 'rm -f /var/lib/mysql-persistent/.restore-completed'`
|
||||
3. Run `docker compose run --rm ac-db-import`
|
||||
|
||||
See [docs/ADVANCED.md#database-hardening](ADVANCED.md#database-hardening) for more background on the tmpfs/persistent split and why the sentinel exists, and review [docs/TROUBLESHOOTING.md](TROUBLESHOOTING.md#database-connection-issues) for quick steps when the automation logs the warning above.
|
||||
@@ -412,26 +416,13 @@ SOURCE /path/to/your/file.sql;
|
||||
docker exec -i ac-mysql mysql -uroot -pPASSWORD acore_world < yourfile.sql
|
||||
```
|
||||
|
||||
### Module SQL Ledger & Deduplication
|
||||
### Module SQL Staging
|
||||
|
||||
`./scripts/bash/stage-modules.sh` now keeps a lightweight ledger at `storage/modules/.modules-meta/module-sql-ledger.txt` (also mounted inside containers at `/azerothcore/modules/.modules-meta/module-sql-ledger.txt`). Each staged SQL file is recorded as:
|
||||
|
||||
```
|
||||
<database-scope>|<module>|<base_filename>|<hash>
|
||||
```
|
||||
|
||||
When the script runs again it hashes every module SQL file and skips any entry whose `(db, module, filename)` already matches with the same hash. This prevents re-copying identical SQL after a backup restore and stops worldserver from reapplying inserts that already exist in the database. If a database restore is detected (`local-storage/mysql-data/.restore-completed` changed), the ledger is automatically reset so every module SQL file is recopied exactly once. The ledger is automatically updated anytime a file changes so only the modified SQL is restaged.
|
||||
|
||||
The stage script also cross-checks MySQL’s `updates` table before copying files and prunes any staged file whose identifier already exists there. That means even if a file gets stuck in `/azerothcore/data/sql/updates/<db>` (e.g., after an interrupted run), it is removed before worldserver starts if the database already recorded it.
|
||||
`./scripts/bash/stage-modules.sh` recopies every enabled module SQL file into `/azerothcore/data/sql/updates/{db_world,db_characters,db_auth}` each time it runs. Files are named deterministically (`MODULE_mod-name_file.sql`) and left on disk permanently. AzerothCore’s auto-updater consults the `updates` tables to decide whether a script needs to run; if it already ran, the entry in `updates` prevents a reapply, but leaving the file in place avoids “missing history” warnings and provides a clear audit trail.
|
||||
|
||||
### Restore-Time SQL Reconciliation
|
||||
|
||||
During a backup restore the `ac-db-import` service now runs `scripts/bash/restore-and-stage.sh`, which consolidates the old restore workflow with module SQL staging. Every backup created by the scheduler now includes a snapshot of the module ledger at `module-sql-ledger.txt` (for example `storage/backups/hourly/20250101_120000/module-sql-ledger.txt`). The restore script:
|
||||
|
||||
- Refreshes `storage/modules/.modules-meta/module-sql-ledger.txt` using the snapshot bundled with the backup (or rebuilds it from the modules directory if the snapshot is missing).
|
||||
- Writes `storage/modules/.modules-meta/.restore-prestaged` to signal that the next `./scripts/bash/stage-modules.sh` run must repopulate `/azerothcore/data/sql/updates/*` before worldserver comes online.
|
||||
|
||||
The staging script now recopies every module SQL file—regardless of whether it has already been applied—using deterministic names like `MODULE_mod-npc-buffer_npc_buffer.sql`. AzerothCore’s built-in updater consults the `updates` tables to decide what should actually run, so already-applied files remain on disk purely to keep history intact and avoid “file missing” warnings. If a legacy backup doesn’t contain the ledger snapshot the helper simply rebuilds it and still sets the flag, so the runtime staging pass behaves the same. Run `rm -f storage/modules/.modules-meta/module-sql-ledger.txt` and rerun `./scripts/bash/stage-modules.sh --yes` if you intentionally need to reseed the ledger from scratch.
|
||||
During a backup restore the `ac-db-import` service now runs `scripts/bash/restore-and-stage.sh`, which simply drops `storage/modules/.modules-meta/.restore-prestaged`. On the next `./scripts/bash/stage-modules.sh --yes`, the script sees the flag, clears any previously staged files, and recopies every enabled SQL file before worldserver boots. Because the files are always present, AzerothCore’s updater has the complete history it needs to apply or skip scripts correctly—no hash/ledger bookkeeping required.
|
||||
|
||||
This snapshot-driven workflow means restoring a new backup automatically replays any newly added module SQL while avoiding duplicate inserts for modules that were already present. See **[docs/ADVANCED.md](ADVANCED.md)** for a deeper look at the marker workflow and container responsibilities.
|
||||
|
||||
@@ -440,16 +431,12 @@ This snapshot-driven workflow means restoring a new backup automatically replays
|
||||
If you intentionally need to reapply all module SQL (for example after manually cleaning tables):
|
||||
|
||||
1. Stop services: `docker compose down`
|
||||
2. Remove the SQL ledger so the next run rehashes everything:
|
||||
```bash
|
||||
rm -f storage/modules/.modules-meta/module-sql-ledger.txt
|
||||
```
|
||||
3. (Optional) Drop the relevant records from the `updates` table if you want AzerothCore to rerun them, e.g.:
|
||||
2. (Optional) Drop the relevant records from the `updates` table if you want AzerothCore to rerun them, e.g.:
|
||||
```bash
|
||||
docker exec -it ac-mysql mysql -uroot -p \
|
||||
-e "DELETE FROM acore_characters.updates WHERE name LIKE '%MODULE_mod-ollama-chat%';"
|
||||
```
|
||||
4. Run `./scripts/bash/stage-modules.sh --yes`
|
||||
3. Run `./scripts/bash/stage-modules.sh --yes`
|
||||
|
||||
Only perform step 3 if you understand the impact—deleting entries causes worldserver to execute those SQL scripts again on next startup.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user