Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion documentation/docs/backup/mysql-backup/mysql_prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,14 @@ Before creating MySQL backups, make sure to:
- [`qpress`][PERCONA_QPRESS].

!!! caution alert alert-warning "Important"
The versions of each must be compatible with the installed version of MySQL.
The versions of each must be compatible with the installed version of MySQL.
Use the Percona XtraBackup version family that matches your MySQL version:

| MySQL version | Percona XtraBackup version |
|---------------|----------------------------|
| MySQL 5.5, 5.6, or 5.7 | Percona XtraBackup 2.4.x |
| MySQL 8.0.0 through 8.0.21 | Percona XtraBackup 8.0.x, using the minimum version required for your MySQL release |
| MySQL 8.0.22 and newer 8.0 releases | Percona XtraBackup 8.0.x with the same or newer core version |
| MySQL 8.4.x | Percona XtraBackup 8.4.x |

Percona XtraBackup 8.4.x supports MySQL 8.4 LTS releases, including future 8.4 patch releases. It does not support backing up MySQL 8.0 or 9.x servers.
137 changes: 113 additions & 24 deletions managed/services/backup/compatibility_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ var (
// processing will be stopped and Percona XtraBackup will not be allowed to continue.
// https://www.percona.com/blog/2020/08/18/aligning-percona-xtrabackup-versions-with-percona-server-for-mysql/
alignedXtrabackupVersion = version.Must(version.NewVersion("8.0.22"))
// Since there is no version 9 or greater let's limit aligning rule by this number.
maxAlignedXtrabackupVersion = version.Must(version.NewVersion("9.0"))
mysql81Version = version.Must(version.NewVersion("8.1.0"))
mysql84Version = version.Must(version.NewVersion("8.4.0"))
mysql85Version = version.Must(version.NewVersion("8.5.0"))

pbmMinSupportedVersion = version.Must(version.NewVersion("2.0.1"))
)
Expand Down Expand Up @@ -66,7 +67,7 @@ func init() {
mysqlMinVersion: "8.0",
mysqlMaxVersion: "8.0.20",
xtrabackupMinVersion: "8.0.6",
xtrabackupMaxVersion: "9.0",
xtrabackupMaxVersion: "8.1.0",
},
// Percona XtraBackup 8.0.12 now supports backup and restore processing for all versions of MySQL;
// previous versions of Percona XtraBackup will not work with MySQL 8.0.20 and higher.
Expand All @@ -78,7 +79,7 @@ func init() {
mysqlMinVersion: "8.0.20",
mysqlMaxVersion: "8.0.21",
xtrabackupMinVersion: "8.0.12",
xtrabackupMaxVersion: "9.0",
xtrabackupMaxVersion: "8.1.0",
},
// Percona XtraBackup 8.0.14 supports backup and restore processing for all versions of MySQL
// and has been tested with the latest MySQL 8.0.21.
Expand All @@ -87,7 +88,7 @@ func init() {
mysqlMinVersion: "8.0.21",
mysqlMaxVersion: "8.0.22",
xtrabackupMinVersion: "8.0.14",
xtrabackupMaxVersion: "9.0",
xtrabackupMaxVersion: "8.1.0",
Comment thread
maxkondr marked this conversation as resolved.
Outdated
},
}

Expand All @@ -108,35 +109,128 @@ func init() {
}

func mysqlAndXtrabackupCompatible(mysqlVersionString, xtrabackupVersionString string) (bool, error) {
mysqlVersion, err := version.NewVersion(mysqlVersionString)
mysqlVersion, xtrabackupVersion, err := mysqlAndXtrabackupCoreVersions(mysqlVersionString, xtrabackupVersionString)
if err != nil {
return false, err
}

return mysqlAndXtrabackupCoreVersionsCompatible(mysqlVersion, xtrabackupVersion), nil
}

func mysqlAndXtrabackupCoreVersions(mysqlVersionString, xtrabackupVersionString string) (*version.Version, *version.Version, error) {
mysqlVersion, err := version.NewVersion(mysqlVersionString)
if err != nil {
return nil, nil, err
}
mysqlVersion = mysqlVersion.Core()

xtrabackupVersion, err := version.NewVersion(xtrabackupVersionString)
if err != nil {
return false, err
return nil, nil, err
}
xtrabackupVersion = xtrabackupVersion.Core()

// See comment to alignedVersion.
// Using compatibility rule.
if mysqlVersion.GreaterThanOrEqual(alignedXtrabackupVersion) {
if xtrabackupVersion.GreaterThanOrEqual(mysqlVersion) && xtrabackupVersion.LessThan(maxAlignedXtrabackupVersion) {
return true, nil
}
} else { // Using compatibility matrix.
return mysqlVersion, xtrabackupVersion, nil
}

type mysqlXtrabackupBand int

const (
mysqlXtrabackupBand84 mysqlXtrabackupBand = iota
mysqlXtrabackupBand80Aligned
mysqlXtrabackupBandLegacy
mysqlXtrabackupBandUnsupported
)

func mysqlXtrabackupBandFor(mysqlVersion *version.Version) mysqlXtrabackupBand {
switch {
case mysqlVersion.GreaterThanOrEqual(mysql84Version) && mysqlVersion.LessThan(mysql85Version):
return mysqlXtrabackupBand84
case mysqlVersion.GreaterThanOrEqual(alignedXtrabackupVersion) && mysqlVersion.LessThan(mysql84Version):
return mysqlXtrabackupBand80Aligned
case mysqlVersion.LessThan(alignedXtrabackupVersion):
return mysqlXtrabackupBandLegacy
default:
return mysqlXtrabackupBandUnsupported
}
}

func incompatibleXtrabackupError(message, xtrabackupVersionString, mysqlVersionString string) error {
return errors.Wrapf(
ErrIncompatibleXtrabackup,
message,
xtrabackupVersionString,
mysqlVersionString,
)
}

func mysqlAndXtrabackupCoreVersionsCompatible(mysqlVersion, xtrabackupVersion *version.Version) bool {
Comment thread
maxkondr marked this conversation as resolved.
switch mysqlXtrabackupBandFor(mysqlVersion) {
case mysqlXtrabackupBand84:
return xtrabackupVersion.GreaterThanOrEqual(mysql84Version) && xtrabackupVersion.LessThan(mysql85Version)
case mysqlXtrabackupBand80Aligned:
return xtrabackupVersion.GreaterThanOrEqual(mysqlVersion) && xtrabackupVersion.LessThan(mysql81Version)
case mysqlXtrabackupBandLegacy:
for _, cv := range mysqlAndXtrabackupCompatibleVersions {
if (mysqlVersion.GreaterThanOrEqual(cv.dbMinVersion) &&
mysqlVersion.LessThan(cv.dbMaxVersion)) &&
if mysqlVersion.GreaterThanOrEqual(cv.dbMinVersion) &&
mysqlVersion.LessThan(cv.dbMaxVersion) &&
xtrabackupVersion.GreaterThanOrEqual(cv.backupToolMinVersion) &&
xtrabackupVersion.LessThan(cv.backupToolMaxVersion) {
return true, nil
return true
}
}
case mysqlXtrabackupBandUnsupported:
return false
}

return false
}

func mysqlAndXtrabackupCompatibilityError(mysqlVersionString, xtrabackupVersionString string) error {
mysqlVersion, xtrabackupVersion, err := mysqlAndXtrabackupCoreVersions(mysqlVersionString, xtrabackupVersionString)
if err != nil {
return err
}
if mysqlAndXtrabackupCoreVersionsCompatible(mysqlVersion, xtrabackupVersion) {
return nil
}

switch mysqlXtrabackupBandFor(mysqlVersion) {
case mysqlXtrabackupBand84:
return incompatibleXtrabackupError(
"Percona XtraBackup version %q is not compatible with MySQL version %q; use Percona XtraBackup 8.4.x for MySQL 8.4.x",
xtrabackupVersionString,
mysqlVersionString,
)
case mysqlXtrabackupBand80Aligned:
if xtrabackupVersion.LessThan(mysqlVersion) {
return incompatibleXtrabackupError(
"Percona XtraBackup version %q is older than MySQL version %q; "+
"for MySQL 8.0.22+, use Percona XtraBackup 8.0.x with the same or newer core version",
xtrabackupVersionString,
mysqlVersionString,
)
}

return incompatibleXtrabackupError(
"Percona XtraBackup version %q is not compatible with MySQL version %q; use Percona XtraBackup 8.0.x for MySQL 8.0.x",
xtrabackupVersionString,
mysqlVersionString,
)
case mysqlXtrabackupBandLegacy:
return incompatibleXtrabackupError(
"Percona XtraBackup version %q is not compatible with MySQL version %q; "+
"install a Percona XtraBackup version supported for this MySQL version",
xtrabackupVersionString,
mysqlVersionString,
)
default:
return incompatibleXtrabackupError(
"PMM does not support Percona XtraBackup version %q with MySQL version %q yet",
xtrabackupVersionString,
mysqlVersionString,
)
}
return false, nil
}

func vendorToServiceType(vendor string) (models.ServiceType, error) {
Expand Down Expand Up @@ -185,14 +279,9 @@ func mySQLBackupSoftwareInstalledAndCompatible(svm map[models.SoftwareName]strin
svm[models.XtrabackupSoftwareName], svm[models.XbcloudSoftwareName])
}

ok, err := mysqlAndXtrabackupCompatible(svm[models.MysqldSoftwareName], svm[models.XtrabackupSoftwareName])
if err != nil {
if err := mysqlAndXtrabackupCompatibilityError(svm[models.MysqldSoftwareName], svm[models.XtrabackupSoftwareName]); err != nil {
return err
}
if !ok {
return errors.Wrapf(ErrIncompatibleXtrabackup, "xtrabackup version %q is not compatible with mysql version %q",
svm[models.XtrabackupSoftwareName], svm[models.MysqldSoftwareName])
}

return nil
}
Expand Down
Loading
Loading