fix(ops): backup failed on the MariaDB client shipped in the API image
Every backup on galactus died with: mysqldump: unknown variable 'set-gtid-purged=OFF' respaldo incompleto eliminado Alpine's mysql-client is MariaDB's, so `mysqldump` inside the API container is a shim over `mariadb-dump`, which has no --set-gtid-purged. That took out BACKUP and, because they take a safety dump first, SYNC and REIMPORT too. Probe `mysqldump --help` and pass the flag only when it is advertised, calling `mariadb-dump` directly otherwise — MariaDB writes no GTID state unless asked with --gtid, so there is nothing to suppress. Testing whether mariadb-dump merely exists would be wrong: on a host carrying both clients it would shadow a perfectly good MySQL mysqldump. The probe uses a command substitution rather than `--help | grep -q` because PIPEFAIL is in effect for these commands and grep closing the pipe early would report a supported flag as unsupported. pre-migrate-backup.mjs is unaffected — it dumps from a real mysql:8.4 image, not from the API container. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -262,9 +262,26 @@ export class OpsService implements OnModuleInit {
|
||||
* deploy/scripts/pre-migrate-backup.mjs — the two write into the same volume
|
||||
* and both are listed as restore points by this same screen.
|
||||
*
|
||||
* --set-gtid-purged=OFF: the production server is the replication SOURCE with
|
||||
* GTID on, so without it every dump embeds SET @@GLOBAL.GTID_PURGED and is
|
||||
* unrestorable onto the very server it came from.
|
||||
* The dumper is probed at runtime rather than assumed. This command runs
|
||||
* inside the API image, whose `mysql-client` is Alpine's — i.e. MariaDB's —
|
||||
* where `mysqldump` is a deprecation-warning shim over `mariadb-dump` that
|
||||
* rejects --set-gtid-purged outright:
|
||||
* mysqldump: unknown variable 'set-gtid-purged=OFF'
|
||||
* which failed every backup, including the safety backups SYNC and REIMPORT
|
||||
* take first. MariaDB's dumper emits no GTID state unless asked (--gtid), so
|
||||
* there is nothing to suppress there; the flag is passed only when the dumper
|
||||
* on PATH advertises it, and the real binary is called directly only in the
|
||||
* MariaDB case (calling `mariadb-dump` whenever it merely exists would pick
|
||||
* it over a MySQL `mysqldump` earlier in PATH on a host carrying both).
|
||||
*
|
||||
* The probe is a command substitution, not `--help | grep -q`: PIPEFAIL is in
|
||||
* effect and grep closing the pipe early would make a supported flag look
|
||||
* unsupported.
|
||||
*
|
||||
* --set-gtid-purged=OFF (MySQL only): the production server is the
|
||||
* replication SOURCE with GTID on, so without it every dump embeds
|
||||
* SET @@GLOBAL.GTID_PURGED and is unrestorable onto the very server it came
|
||||
* from.
|
||||
*
|
||||
* The table-count assertion is not belt-and-braces: `gzip -t` passes on the
|
||||
* ~372-byte output of a mysqldump that died on its first statement, so a
|
||||
@@ -277,8 +294,12 @@ export class OpsService implements OnModuleInit {
|
||||
*/
|
||||
private dumpCommand(flags: string, db: string, out: string): string {
|
||||
return (
|
||||
`( mysqldump ${flags} --single-transaction --routines --triggers ` +
|
||||
`--no-tablespaces --set-gtid-purged=OFF ${db} | gzip -c > ${out} && ` +
|
||||
`DUMP=mysqldump; GTID=; ` +
|
||||
`case "$(mysqldump --help 2>/dev/null || true)" in ` +
|
||||
`*set-gtid-purged*) GTID=--set-gtid-purged=OFF;; ` +
|
||||
`*) command -v mariadb-dump >/dev/null 2>&1 && DUMP=mariadb-dump;; esac; ` +
|
||||
`( $DUMP ${flags} --single-transaction --routines --triggers ` +
|
||||
`--no-tablespaces $GTID ${db} | gzip -c > ${out} && ` +
|
||||
`gzip -t ${out} && ` +
|
||||
`TABLAS=$(gunzip -c ${out} | grep -c 'CREATE TABLE') && ` +
|
||||
`echo "tablas capturadas: $TABLAS" && ` +
|
||||
|
||||
Reference in New Issue
Block a user