FEATURE (mysql): Add MySQL 9.x support

This commit is contained in:
Rostislav Dugin
2025-12-24 14:49:26 +03:00
parent 8c00801feb
commit 54a6a30024
22 changed files with 73 additions and 6908 deletions

View File

@@ -191,6 +191,7 @@ jobs:
TEST_MYSQL_57_PORT=33057
TEST_MYSQL_80_PORT=33080
TEST_MYSQL_84_PORT=33084
TEST_MYSQL_90_PORT=33090
# testing MariaDB
TEST_MARIADB_55_PORT=33055
TEST_MARIADB_101_PORT=33101
@@ -259,6 +260,8 @@ jobs:
timeout 120 bash -c 'until docker exec test-mysql-80 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
echo "Waiting for MySQL 8.4..."
timeout 120 bash -c 'until docker exec test-mysql-84 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
echo "Waiting for MySQL 9.0..."
timeout 120 bash -c 'until docker exec test-mysql-90 mysqladmin ping -h localhost -u root -prootpassword --silent 2>/dev/null; do sleep 2; done'
# Wait for MariaDB containers
echo "Waiting for MariaDB 5.5..."
@@ -319,7 +322,7 @@ jobs:
uses: actions/cache@v4
with:
path: backend/tools/mysql
key: mysql-clients-57-80-84-v1
key: mysql-clients-57-80-84-9-v1
- name: Cache MariaDB client tools
id: cache-mariadb

View File

@@ -80,7 +80,7 @@ ENV ENV_MODE=production
# ========= STEP 1: Install base packages =========
RUN apt-get update
RUN apt-get install -y --no-install-recommends \
wget ca-certificates gnupg lsb-release sudo gosu curl unzip xz-utils libncurses5
wget ca-certificates gnupg lsb-release sudo gosu curl unzip xz-utils libncurses5 libncurses6
RUN rm -rf /var/lib/apt/lists/*
# ========= Install PostgreSQL client binaries (versions 12-18) =========
@@ -130,10 +130,11 @@ RUN apt-get update && \
# Create directories for all database clients
RUN mkdir -p /usr/local/mysql-5.7/bin /usr/local/mysql-8.0/bin /usr/local/mysql-8.4/bin \
/usr/local/mysql-9/bin \
/usr/local/mariadb-10.6/bin /usr/local/mariadb-12.1/bin \
/usr/local/mongodb-database-tools/bin
# ========= Install MySQL clients (5.7, 8.0, 8.4) =========
# ========= Install MySQL clients (5.7, 8.0, 8.4, 9) =========
# Pre-downloaded binaries from assets/tools/ - no network download needed
# Note: MySQL 5.7 is only available for x86_64
# Note: MySQL binaries require libncurses5 for terminal handling
@@ -142,11 +143,13 @@ COPY assets/tools/arm/mysql/ /tmp/mysql-arm/
RUN if [ "$TARGETARCH" = "amd64" ]; then \
cp /tmp/mysql-x64/mysql-5.7/bin/* /usr/local/mysql-5.7/bin/ && \
cp /tmp/mysql-x64/mysql-8.0/bin/* /usr/local/mysql-8.0/bin/ && \
cp /tmp/mysql-x64/mysql-8.4/bin/* /usr/local/mysql-8.4/bin/; \
cp /tmp/mysql-x64/mysql-8.4/bin/* /usr/local/mysql-8.4/bin/ && \
cp /tmp/mysql-x64/mysql-9/bin/* /usr/local/mysql-9/bin/; \
elif [ "$TARGETARCH" = "arm64" ]; then \
echo "MySQL 5.7 not available for arm64, skipping..." && \
cp /tmp/mysql-arm/mysql-8.0/bin/* /usr/local/mysql-8.0/bin/ && \
cp /tmp/mysql-arm/mysql-8.4/bin/* /usr/local/mysql-8.4/bin/; \
cp /tmp/mysql-arm/mysql-8.4/bin/* /usr/local/mysql-8.4/bin/ && \
cp /tmp/mysql-arm/mysql-9/bin/* /usr/local/mysql-9/bin/; \
fi && \
rm -rf /tmp/mysql-x64 /tmp/mysql-arm && \
chmod +x /usr/local/mysql-*/bin/*

View File

@@ -1,8 +1,8 @@
<div align="center">
<img src="assets/logo.svg" style="margin-bottom: 20px;" alt="Postgresus Logo" width="250"/>
<h3>PostgreSQL backup</h3>
<p>Free, open source and self-hosted solution for automated PostgreSQL backups. With multiple storage options and notifications</p>
<h3>PostgreSQL Backup</h3>
<p>A free, open source and self-hosted solution for automated PostgreSQL backups with multiple storage options and notifications.</p>
<!-- Badges -->
[![Apache 2.0 License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](LICENSE)
@@ -63,9 +63,9 @@
### 🔒 **Enterprise-grade security** <a href="https://postgresus.com/security">(docs)</a>
- **AES-256-GCM encryption**: Enterprise-grade protection for backup files
- **Zero-trust storage**: Backups are encrypted and they are useless to attackers, so you can keep them in shared storages like S3, Azure Blob Storage, etc.
- **Zero-trust storage**: Backups are encrypted and remain useless to attackers, so you can safely store them in shared storage like S3, Azure Blob Storage, etc.
- **Encryption for secrets**: Any sensitive data is encrypted and never exposed, even in logs or error messages
- **Read-only user**: Postgresus uses by default a read-only user for backups and never stores anything that can change your data
- **Read-only user**: Postgresus uses a read-only user by default for backups and never stores anything that can modify your data
### 👥 **Suitable for teams** <a href="https://postgresus.com/access-management">(docs)</a>
@@ -86,7 +86,7 @@ Postgresus works seamlessly with both self-hosted PostgreSQL and cloud-managed d
- **Cloud support**: AWS RDS, Google Cloud SQL, Azure Database for PostgreSQL
- **Self-hosted**: Any PostgreSQL instance you manage yourself
- **Why no PITR?**: Cloud providers already offer native PITR, and external PITR backups cannot be restored to managed cloud databases — making them impractical for cloud-hosted PostgreSQL
- **Why no PITR support?**: Cloud providers already offer native PITR, and external PITR backups cannot be restored to managed cloud databases — making them impractical for cloud-hosted PostgreSQL
- **Practical granularity**: Hourly and daily backups are sufficient for 99% of projects without the operational complexity of WAL archiving
### 🐳 **Self-hosted & secure**
@@ -97,11 +97,12 @@ Postgresus works seamlessly with both self-hosted PostgreSQL and cloud-managed d
### 📦 Installation <a href="https://postgresus.com/installation">(docs)</a>
You have several ways to install Postgresus:
You have four ways to install Postgresus:
- Script (recommended)
- Automated script (recommended)
- Simple Docker run
- Docker Compose setup
- Kubernetes with Helm
<img src="assets/healthchecks.svg" alt="Postgresus Dashboard" width="800"/>
@@ -211,7 +212,7 @@ For more options (NodePort, TLS, HTTPRoute for Gateway API), see the [Helm chart
## 🚀 Usage
1. **Access the dashboard**: Navigate to `http://localhost:4005`
2. **Add first DB for backup**: Click "New Database" and follow the setup wizard
2. **Add your first database for backup**: Click "New Database" and follow the setup wizard
3. **Configure schedule**: Choose from hourly, daily, weekly, monthly or cron intervals
4. **Set database connection**: Enter your PostgreSQL credentials and connection details
5. **Choose storage**: Select where to store your backups (local, S3, Google Drive, etc.)
@@ -238,4 +239,4 @@ This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENS
## 🤝 Contributing
Contributions are welcome! Read <a href="https://postgresus.com/contribute">contributing guide</a> for more details, priorities and rules are specified there. If you want to contribute, but don't know what and how - message me on Telegram [@rostislav_dugin](https://t.me/rostislav_dugin)
Contributions are welcome! Read the <a href="https://postgresus.com/contribute">contributing guide</a> for more details, priorities and rules. If you want to contribute but don't know where to start, message me on Telegram [@rostislav_dugin](https://t.me/rostislav_dugin)

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -213,6 +213,25 @@ services:
timeout: 5s
retries: 10
test-mysql-90:
image: mysql:9.5
ports:
- "${TEST_MYSQL_90_PORT:-33090}:3306"
environment:
- MYSQL_ROOT_PASSWORD=rootpassword
- MYSQL_DATABASE=testdb
- MYSQL_USER=testuser
- MYSQL_PASSWORD=testpassword
command: --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
volumes:
- ./mysqldata/mysql-90:/var/lib/mysql
container_name: test-mysql-90
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-prootpassword"]
interval: 5s
timeout: 5s
retries: 10
# Test MariaDB containers
test-mariadb-55:
image: mariadb:5.5

View File

@@ -57,6 +57,7 @@ type EnvVariables struct {
TestMysql57Port string `env:"TEST_MYSQL_57_PORT"`
TestMysql80Port string `env:"TEST_MYSQL_80_PORT"`
TestMysql84Port string `env:"TEST_MYSQL_84_PORT"`
TestMysql90Port string `env:"TEST_MYSQL_90_PORT"`
TestMariadb55Port string `env:"TEST_MARIADB_55_PORT"`
TestMariadb101Port string `env:"TEST_MARIADB_101_PORT"`

View File

@@ -133,7 +133,7 @@ func (uc *CreateMysqlBackupUsecase) getNetworkCompressionArgs(version tools.Mysq
const zstdCompressionLevel = 5
switch version {
case tools.MysqlVersion80, tools.MysqlVersion84:
case tools.MysqlVersion80, tools.MysqlVersion84, tools.MysqlVersion9:
return []string{
"--compression-algorithms=zstd",
fmt.Sprintf("--zstd-compression-level=%d", zstdCompressionLevel),

View File

@@ -370,7 +370,7 @@ func mapMysqlVersion(major, minor string) (tools.MysqlVersion, error) {
case "8":
return mapMysql8xVersion(minor), nil
case "9":
return tools.MysqlVersion84, nil
return tools.MysqlVersion9, nil
default:
return "", fmt.Errorf(
"unsupported MySQL major version: %s (supported: 5.x, 8.x, 9.x)",

View File

@@ -28,6 +28,7 @@ func Test_IsUserReadOnly_AdminUser_ReturnsFalse(t *testing.T) {
{"MySQL 5.7", tools.MysqlVersion57, env.TestMysql57Port},
{"MySQL 8.0", tools.MysqlVersion80, env.TestMysql80Port},
{"MySQL 8.4", tools.MysqlVersion84, env.TestMysql84Port},
{"MySQL 9", tools.MysqlVersion9, env.TestMysql90Port},
}
for _, tc := range cases {
@@ -58,6 +59,7 @@ func Test_CreateReadOnlyUser_UserCanReadButNotWrite(t *testing.T) {
{"MySQL 5.7", tools.MysqlVersion57, env.TestMysql57Port},
{"MySQL 8.0", tools.MysqlVersion80, env.TestMysql80Port},
{"MySQL 8.4", tools.MysqlVersion84, env.TestMysql84Port},
{"MySQL 9", tools.MysqlVersion9, env.TestMysql90Port},
}
for _, tc := range cases {

View File

@@ -75,6 +75,7 @@ func Test_BackupAndRestoreMysql_RestoreIsSuccessful(t *testing.T) {
{"MySQL 5.7", tools.MysqlVersion57, env.TestMysql57Port},
{"MySQL 8.0", tools.MysqlVersion80, env.TestMysql80Port},
{"MySQL 8.4", tools.MysqlVersion84, env.TestMysql84Port},
{"MySQL 9", tools.MysqlVersion9, env.TestMysql90Port},
}
for _, tc := range cases {
@@ -95,6 +96,7 @@ func Test_BackupAndRestoreMysqlWithEncryption_RestoreIsSuccessful(t *testing.T)
{"MySQL 5.7", tools.MysqlVersion57, env.TestMysql57Port},
{"MySQL 8.0", tools.MysqlVersion80, env.TestMysql80Port},
{"MySQL 8.4", tools.MysqlVersion84, env.TestMysql84Port},
{"MySQL 9", tools.MysqlVersion9, env.TestMysql90Port},
}
for _, tc := range cases {
@@ -115,6 +117,7 @@ func Test_BackupAndRestoreMysql_WithReadOnlyUser_RestoreIsSuccessful(t *testing.
{"MySQL 5.7", tools.MysqlVersion57, env.TestMysql57Port},
{"MySQL 8.0", tools.MysqlVersion80, env.TestMysql80Port},
{"MySQL 8.4", tools.MysqlVersion84, env.TestMysql84Port},
{"MySQL 9", tools.MysqlVersion9, env.TestMysql90Port},
}
for _, tc := range cases {

View File

@@ -17,6 +17,7 @@ const (
MysqlVersion57 MysqlVersion = "5.7"
MysqlVersion80 MysqlVersion = "8.0"
MysqlVersion84 MysqlVersion = "8.4"
MysqlVersion9 MysqlVersion = "9"
)
type MysqlExecutable string
@@ -45,7 +46,7 @@ func GetMysqlExecutable(
return filepath.Join(basePath, executableName)
}
// VerifyMysqlInstallation verifies that MySQL versions 5.7, 8.0, 8.4 are installed
// VerifyMysqlInstallation verifies that MySQL versions 5.7, 8.0, 8.4, 9 are installed
// in the current environment. Each version should be installed with the required
// client tools (mysqldump, mysql) available.
// In development: ./tools/mysql/mysql-{VERSION}/bin
@@ -59,6 +60,7 @@ func VerifyMysqlInstallation(
MysqlVersion57,
MysqlVersion80,
MysqlVersion84,
MysqlVersion9,
}
requiredCommands := []MysqlExecutable{
@@ -171,6 +173,7 @@ func IsMysqlBackupVersionHigherThanRestoreVersion(
MysqlVersion57: 1,
MysqlVersion80: 2,
MysqlVersion84: 3,
MysqlVersion9: 4,
}
return versionOrder[backupVersion] > versionOrder[restoreVersion]
}
@@ -193,6 +196,8 @@ func GetMysqlVersionEnum(version string) MysqlVersion {
return MysqlVersion80
case "8.4":
return MysqlVersion84
case "9":
return MysqlVersion9
default:
panic(fmt.Sprintf("invalid mysql version: %s", version))
}

View File

@@ -1,4 +1,5 @@
postgresql
mysql
downloads
mariadb
mariadb
mongodb

View File

@@ -95,11 +95,11 @@ done
# ========== MySQL Installation ==========
echo "========================================"
echo "Installing MySQL client tools (versions 5.7, 8.0, 8.4)..."
echo "Installing MySQL client tools (versions 5.7, 8.0, 8.4, 9)..."
echo "========================================"
# Download and extract MySQL client tools
mysql_versions="5.7 8.0 8.4"
mysql_versions="5.7 8.0 8.4 9"
for version in $mysql_versions; do
echo "Installing MySQL $version client tools..."
@@ -108,7 +108,7 @@ for version in $mysql_versions; do
mkdir -p "$version_dir/bin"
# Download MySQL client tools from official CDN
# Note: 5.7 is in Downloads, 8.0 and 8.4 specific versions are in archives
# Note: 5.7 is in Downloads, 8.0, 8.4 specific versions are in archives, 9.5 is in MySQL-9.5
case $version in
"5.7")
MYSQL_URL="https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz"
@@ -119,6 +119,9 @@ for version in $mysql_versions; do
"8.4")
MYSQL_URL="https://cdn.mysql.com/archives/mysql-8.4/mysql-8.4.3-linux-glibc2.17-x86_64-minimal.tar.xz"
;;
"9")
MYSQL_URL="https://dev.mysql.com/get/Downloads/MySQL-9.5/mysql-9.5.0-linux-glibc2.28-x86_64.tar.xz"
;;
esac
TEMP_DIR="/tmp/mysql_install_$version"

View File

@@ -129,7 +129,7 @@ done
# ========== MySQL Installation ==========
echo "========================================"
echo "Installing MySQL client tools (versions 5.7, 8.0, 8.4)..."
echo "Installing MySQL client tools (versions 5.7, 8.0, 8.4, 9)..."
echo "========================================"
# Detect architecture
@@ -141,11 +141,12 @@ else
fi
# MySQL download URLs for macOS (using CDN)
# Note: 5.7 is in Downloads, 8.0 and 8.4 specific versions are in archives
# Note: 5.7 is in Downloads, 8.0, 8.4 specific versions are in archives, 9.5 is in MySQL-9.5
declare -A MYSQL_URLS=(
["5.7"]="https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-5.7.44-macos10.14-x86_64.tar.gz"
["8.0"]="https://cdn.mysql.com/archives/mysql-8.0/mysql-8.0.40-macos14-${MYSQL_ARCH}.tar.gz"
["8.4"]="https://cdn.mysql.com/archives/mysql-8.4/mysql-8.4.3-macos14-${MYSQL_ARCH}.tar.gz"
["9"]="https://dev.mysql.com/get/Downloads/MySQL-9.5/mysql-9.5.0-macos14-${MYSQL_ARCH}.tar.gz"
)
# Function to install MySQL client tools
@@ -203,7 +204,7 @@ install_mysql_client() {
}
# Install each MySQL version
mysql_versions="5.7 8.0 8.4"
mysql_versions="5.7 8.0 8.4 9"
for version in $mysql_versions; do
url=${MYSQL_URLS[$version]}

View File

@@ -107,18 +107,19 @@ for %%v in (%pg_versions%) do (
:: ========== MySQL Installation ==========
echo ========================================
echo Installing MySQL client tools (versions 5.7, 8.0, 8.4)...
echo Installing MySQL client tools (versions 5.7, 8.0, 8.4, 9)...
echo ========================================
echo.
:: MySQL download URLs for Windows x64 (ZIP archives) - using CDN
:: Note: 5.7 is in Downloads, 8.0 and 8.4 specific versions are in archives
:: Note: 5.7 is in Downloads, 8.0, 8.4 specific versions are in archives, 9.5 is in MySQL-9.5
set "MYSQL57_URL=https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-5.7.44-winx64.zip"
set "MYSQL80_URL=https://cdn.mysql.com/archives/mysql-8.0/mysql-8.0.40-winx64.zip"
set "MYSQL84_URL=https://cdn.mysql.com/archives/mysql-8.4/mysql-8.4.3-winx64.zip"
set "MYSQL9_URL=https://dev.mysql.com/get/Downloads/MySQL-9.5/mysql-9.5.0-winx64.zip"
:: MySQL versions
set "mysql_versions=5.7 8.0 8.4"
set "mysql_versions=5.7 8.0 8.4 9"
:: Download and install each MySQL version
for %%v in (%mysql_versions%) do (

View File

@@ -1,6 +1,6 @@
This directory is needed only for development and CI\CD.
We have to download and install all the PostgreSQL versions from 12 to 18, MySQL versions 5.7, 8.0, 8.4, MariaDB client tools and MongoDB Database Tools locally.
We have to download and install all the PostgreSQL versions from 12 to 18, MySQL versions 5.7, 8.0, 8.4, 9, MariaDB client tools and MongoDB Database Tools locally.
This is needed so we can call pg_dump, pg_restore, mysqldump, mysql, mariadb-dump, mariadb, mongodump, mongorestore, etc. on each version of the database.
You do not need to install the databases fully with all the components.
@@ -23,6 +23,7 @@ We only need the client tools for each version.
- MySQL 5.7
- MySQL 8.0
- MySQL 8.4
- MySQL 9
### MariaDB
@@ -127,6 +128,7 @@ For example:
- `./tools/mysql/mysql-5.7/bin/mysqldump`
- `./tools/mysql/mysql-8.0/bin/mysqldump`
- `./tools/mysql/mysql-8.4/bin/mysqldump`
- `./tools/mysql/mysql-9/bin/mysqldump`
### MariaDB