Upgrading to 3.0
Move from GoArchive 2.x or earlier to 3.0: the tracking tables, the configuration, the command line, and the limits that changed.
GoArchive 3.0 does not read or migrate the tracking tables of earlier versions, and it reads its configuration file strictly. Plan the upgrade as a short maintenance step: finish the running jobs with your current version, then switch.
The short version
- Finish every job with your current version, then drop its tracking tables (Moving from 2.x ). GoArchive 3.0 never reads or migrates them.
- Rewrite the configuration: every job needs
job_type,verificationis one value, and unknown keys are refused (Configuration changes ). - Grant
TRIGGERdirectly on the job tables: on the source for archive and purge, and on the destination for archive and copy-only. The 2.x grant recipes lack it, and preflight refuses the job without it (Permissions ). - Drop
--forceand--skip-verifyfrom your scripts, rename--skip-validate-preflight, and check how the scripts read exit codes (Command-line changes ). - Run
goarchive validate. Preflight in 3.0 checks keys and relations more strictly than 2.x did.
A 2.x configuration file fails to load with an error that points to the upgrade guide, and 2.x tracking tables are refused at startup.
Moving from 2.x
The tracking tables in 3.0 are new: a typed log per job and a job binding, with no checkpoint (Tracking Tables ). A tracking schema written by an earlier version is refused, and nothing is migrated.
Finish every job with your current version, so that no log row is left pending or copied. Retire a job you cannot finish, as your current version’s documentation describes.
Stop every GoArchive process that uses the tracking schema.
Drop the old tracking tables in
job_schema, as a DBA. GoArchive’s own account holds noDROPprivilege.-- Generate the DROP statements for every log table (substitute your job_schema for -- goarchive), review them, run them. SELECT CONCAT('DROP TABLE `', table_schema, '`.`', table_name, '`;') FROM information_schema.tables WHERE table_schema = 'goarchive' AND table_name LIKE 'archiver_job_log%'; DROP TABLE goarchive.archiver_job; DROP TABLE goarchive.goarchive_meta;Export the old logs first if the record of what was archived has compliance value. Alternatively, point
destination.job_schemaat a new, empty schema.Run 3.0. The first run labels the schema and registers each job afresh. Every run starts at the beginning of the job’s
whererange. For archive and purge, the rows already processed are gone from the source. A copy-only job would copy everything again, so point it at an empty destination, or give it awherethat starts after what the earlier version copied.
What else is new against 2.x
- Destination tables must be InnoDB.
archiveandcopy-onlyrefuse a destination table on another engine, andvalidateanddry-runreport it. A destination whose columns are in a different order from the source is accepted, with one warning per table. - Archive recovery checks the destination before it deletes. When a run resumes interrupted work, each row of a logged root must already be in the destination before any of it is deleted; otherwise the run stops and deletes nothing. Recovery reads the destination even under
verification: none, so the archive account needsSELECTon the destination tables. An archive job is also bound to its destination database while its log holds copied roots. - Large rows are copied. GoArchive reads each server’s
max_allowed_packetwhen it connects. Only a single value larger than the destination’s packet, or rarely a whole INSERT, fails its batch, with an error that names the table and the remedy. TRIGGERmust be provable on every job table, granted directly to the account. ATRIGGERprivilege held only through a role is refused.--force-triggersdoes not cover these checks.- A self-referencing
ON DELETE CASCADEorSET NULLon a job table is refused for archive and purge, because deleting a batch row would change rows of that table outside the batch. - A job column in an unsupported character set is refused. Every session runs in
utf8mb4, and preflight refuses a column whose character set does not survive that session exactly (Character Sets ). - A stopped job with unfinished work holds its tables. Another job on the same source data whose tree shares one of those tables is refused until the stopped job’s next run finishes its work (Concurrency and locking ).
- Output and exit codes: a run prints its report on stdout only with
--progress, warnings go to stderr, and the exit code tells a stop (3) and a run held by another live run (4) apart from a failure (1) (Output, Progress and Exit Codes ). - Warnings before a run:
verification: count,verification: none, and JSON columns under either mode each print a warning, because those modes do not compare copied values. - The container image runs as UID 65532 from
/work, not as root. A configuration file mounted under/root/is no longer readable; mount it under/work/(Installation ). - Log files are created readable by their owner only (
0600) on Unix, and a run’s log ends with one entry that says how the run ended, with its counts.
Configuration changes
The file is read strictly (Configuration ).
Every job needs
job_type:archive,purgeorcopy-only. A job runs only under that command.primary_key,foreign_keyandreferencesmay be lists, for composite keys.primary_keymust name exactly the table’sPRIMARY KEYcolumns, in key order.referencesnames the parent’s key columns, paired withforeign_keyby position, and may be omitted only when the parent key has one column.verificationis one value:sha256(the default),countornone, globally or per job. The 2.x block (method,skip_verification) is refused:2.x 3.0 method: countverification: countmethod: sha256verification: sha256(the default)skip_verification: trueverification: noneEach job type accepts only the settings it uses. A purge job with
verification, or a copy-only job withbatch_delete_sizeordelete_sleep_seconds, is refused.resumeis a copy-only setting.Unknown keys are refused. Key names are exact and lowercase:
Root_Tableis refused. A helper key such asx-defaults:is refused too, so a YAML anchor shared by merge keys must live under a known key, for example a real job.Job names keep their case. The name on the command line must match the file exactly, and two names that differ only in case are refused. Names must be printable ASCII without spaces, must not start with
-, and can be at most 255 characters.A table may appear once in a job.
One YAML document per file: a second document after
---is refused rather than ignored.The 2.0 replica keys are refused:
2.0 3.0 replica:(one server)replication.servers:(a list)replica.host/port/user/passwordreplication.servers[].host/port/user/passwordreplica.replication_channel: "billing"replication.servers[].channels: ["billing"]replica.replication_channel: ""replication.servers[].channels: [""], the default channel only; omitted or[]checks every channelsafety.lag_thresholdreplication.seconds_behind_source_withinsafety.check_intervalreplication.check_intervalA new log file is readable by its owner only on Unix (
0600; 2.x created it0644). On Windows it inherits its folder’s permissions. An existing file keeps its mode.
Command-line changes
| 2.x | 3.0 |
|---|---|
--skip-verify | --verification=none; --verification=<sha256|count|none> overrides the file for one run |
--force | Removed. A copy-only rerun uses resume: true; a held job lock is never taken over |
--skip-validate-preflight | Renamed --skip-dangerously-validate-preflight-allow-experimental; the old name is refused |
| Every error exited 1; a stop exited 0 | 0 done, 1 failed, 2 usage or configuration error, 3 stopped, 4 a live run holds the work |
| A run printed its report on stdout | A run prints to stdout only with --progress or a stdout log; warnings and errors go to stderr |
dry-run inserted a sample into the destination and rolled it back | dry-run writes nothing: it prints MySQL’s query plans for the first batch’s statements |
validate ran every check on every job | validate checks each job under its job_type |
Limits removed or changed
| 2.x | 3.0 |
|---|---|
| Single-column primary keys only; a foreign key spanning several columns between job tables was refused | Composite primary keys and composite foreign keys are supported at the root and at every child |
| Root keys had to be integers | Root keys may be any supported key type: integer, DECIMAL, string, binary or temporal. FLOAT/DOUBLE, ENUM/SET, BIT and prefix key parts are refused |
| A job continued from a saved checkpoint, so a row that became eligible below the checkpoint was never archived | There is no checkpoint: every run starts at the beginning of the where range, and a row that becomes eligible later is found by the next run |
| An interrupted batch could be copied again during recovery | A batch’s copy, verification and log entry commit together, so recovery only finishes the deletes an archive or purge run had logged |
| A job name was bound to its command and root table only | A job is also bound to its root key, its source server and schema, and its relations (purge: also its where; archive and copy-only: also their destination database). A changed root key is refused; a changed binding is refused while the job has logged work that depends on it |
| The verification method chose the INSERT strategy | Every copy is a strict INSERT: a row already in the destination fails the batch |
| Community and Enterprise editions | One edition, and the version carries no edition suffix |
Coming from a release before 2.2
GoArchive 3.0 keeps what 2.0 to 2.2 introduced. If you skip those releases:
Grants must be provable: each privilege granted directly to the account, and
PROCESSon the source for archive and purge (Permissions ).Sessions are UTC:
whereruns in a UTC session, so aDATETIMEcolumn compared withNOW(), aTIMESTAMPcolumn compared with a bare literal, andCURDATE()boundaries fall at UTC rather than in the server’s time zone.last_heartbeat_atis UTC: measure its age withUTC_TIMESTAMP().TIMESTAMPvalues archived before 2.2 may be wrong when the source and destination sessions ran in different time zones: each copy took the source’s wall-clock text, and the destination read it in its own zone. A DBA can repair them once:-- 1. Back the table up. -- 2. A non-zero count means a zone name is not recognised and the UPDATE would NULL -- the column: stop. SET time_zone = '+00:00'; SELECT COUNT(*) FROM archive.orders WHERE <only rows archived before 2.2> AND ts IS NOT NULL AND CONVERT_TZ(CONVERT_TZ(ts, '+00:00', '<zone the old DESTINATION sessions used>'), '<zone the old SOURCE sessions used>', '+00:00') IS NULL; -- 3. Repair, exactly once per column. UPDATE archive.orders SET ts = CONVERT_TZ(CONVERT_TZ(ts, '+00:00', '<zone the old DESTINATION sessions used>'), '<zone the old SOURCE sessions used>', '+00:00') WHERE <only rows archived before 2.2>;Name the zones as the old sessions saw them (
SYSTEMmeans the server’s operating-system zone). A second run corrupts the values again. Values that fell in a daylight-saving fall-back hour cannot be recovered.
