Skip to content

MySQL 8.0+

Subset and anonymize MySQL into safe staging databases in seconds.

Replace full mysqldump and restore cycles with a MySQL-aware CLI. Subveil selects a foreign-key-connected slice, masks configured values as rows are read, and writes batched inserts to your target.

subveil.yaml — MySQL excerpt
version: 1engine: mysqlsource:  dsn_env: SUBVEIL_SOURCE_DSNtarget:  dsn_env: SUBVEIL_TARGET_DSN

Why mysqldump and in-place masking fail staging workflows

A full backup is not a connected test dataset

Full mysqldump workflows export and restore rows you do not need before tests can run. Subveil opens a read-only InnoDB transaction with START TRANSACTION WITH CONSISTENT SNAPSHOT, follows foreign-key edges from selected roots, and masks rows before inserting them in bounded multi-row batches (up to 250 rows or 8 MiB per batch).

Updating production generates avoidable undo and redo work

In-place UPDATE masking rewrites records and creates InnoDB undo/redo activity, while an interrupted rewrite can leave the source changed. Subveil reads the source and writes masked values only to the separate target. The source account should be read-only and limited to the required schema.

MySQL-native schema and load behavior

The MySQL engine uses MySQL catalog metadata and SQL behavior rather than PostgreSQL dump or restore commands.

subveil.yaml
version: 1engine: mysql​source:  dsn_env: SUBVEIL_SOURCE_DSN​target:  dsn_env: SUBVEIL_TARGET_DSN​masking:  seed_env: SUBVEIL_SEED​subset:  roots:    - table: accounts      where: "status = 'active'"​tables:  customers:    columns:      email:        transformer: email      profile:        transformer: jsonb        paths:          - path: "$.customer.email"            transformer: email      remote_addr:        transformer: ip

DDL from SHOW CREATE TABLE

With --create-schema, Subveil reads table definitions using SHOW CREATE TABLE and creates the target tables; it does not need an external mysqldump binary. Generated VIRTUAL and STORED columns are omitted from inserts so MySQL recomputes them.

AUTO_INCREMENT and foreign-key loading

After loading, Subveil resets each AUTO_INCREMENT value beyond the imported keys. It turns off target-session FOREIGN_KEY_CHECKS and UNIQUE_CHECKS during writes, restores them afterward, and uses the foreign-key graph to select and order dependent rows. MySQL JSON documents support selected JSONPath masking through the jsonb transformer.

MySQL schema DDL can implicitly commit, so schema creation is not rolled back with a failed row load. Review the target and use a dedicated empty preview database.

Use MySQL in managed or self-hosted environments

Subveil supports MySQL 8.0+ across self-hosted and managed deployments. This includes AWS RDS for MySQL, Aurora MySQL, Google Cloud SQL for MySQL, and DigitalOcean Managed MySQL when the runner can connect and has the required database permissions.

Build a MySQL pull-request preview in GitHub Actions

Use a MySQL service container for the target, set engine: mysql in the checked-in config, set SUBVEIL_VERSION to a published CLI version, and store source access and the masking seed as repository secrets.

.github/workflows/mysql-preview.yml
name: MySQL masked previewon:  pull_request:    types: [opened, synchronize, reopened]​jobs:  preview:    runs-on: ubuntu-latest    services:      mysql:        image: mysql:8.4        env:          MYSQL_ROOT_PASSWORD: subveil          MYSQL_DATABASE: subveil_pr        ports: ["3306:3306"]        options: >-          --health-cmd "mysqladmin ping -h 127.0.0.1 -uroot -psubveil"          --health-interval 5s --health-timeout 5s --health-retries 20    env:      SUBVEIL_VERSION: ${{ vars.SUBVEIL_VERSION }}      SUBVEIL_SOURCE_DSN: ${{ secrets.SUBVEIL_SOURCE_DSN }}      SUBVEIL_TARGET_DSN: mysql://root:[email protected]:3306/subveil_pr      SUBVEIL_SEED: ${{ secrets.SUBVEIL_SEED }}    steps:      - uses: actions/checkout@v4      - name: Install Subveil        run: curl -fsSL https://subveil.dev/install.sh | sh -s -- --version "$SUBVEIL_VERSION"      - name: Build masked preview        run: subveil pull --config subveil.yaml --create-schema -j 4

MySQL data masking FAQ

How to subset a MySQL database while keeping foreign keys intact?

Set engine: mysql in subveil.yaml, define one or more root tables and optional row filters, then preview the graph with subveil plan. Subveil follows referenced rows, orders tables by foreign-key dependencies, and disables target-session foreign-key checks during loading before restoring them.

Does Subveil require mysqldump to recreate target schemas?

No. For MySQL, --create-schema reads each table definition with SHOW CREATE TABLE and creates it on the target. The CLI does not require an external mysqldump binary.

How does Subveil mask values inside MySQL JSON columns?

Configure the JSON column with transformer: jsonb and list JSONPath entries such as $.customer.email. Subveil applies an in-process transformer to matching JSON values and retains unlisted values in the document.

Can I use Subveil with managed MySQL or MariaDB?

Subveil works with MySQL 8.0+ in self-hosted and managed environments, including AWS RDS for MySQL, Aurora MySQL, Google Cloud SQL for MySQL, and DigitalOcean Managed MySQL, when network access and database permissions are configured.

Read the full CLI documentation