Presift

Converting a table's character set or collation on a live MySQL table

The classic utf8utf8mb4 migration. On MySQL 8.0, ALTER TABLE … CONVERT TO CHARACTER SET rewrites every row and does not permit concurrent DML while it runs. On a busy table that is an outage.

What the manual says

OperationInstantIn placeRebuilds tablePermits concurrent DML
Converting a character set (CONVERT TO CHARACTER SET)NoYesYes*No
Changing the table character set / collation default only (CHARACTER SET = …)NoYesYes* (if the encoding differs)Yes

Source: MySQL 8.0 Reference Manual, Online DDL Operations → Table operations. * The table is rebuilt when the new encoding differs.

Two consequences: the whole table is rewritten (I/O, disk space for the copy, replica lag), and while CONVERT TO CHARACTER SET runs, writes wait. Waiting writes hold connections; the ALTER also needs an exclusive metadata lock at the start and end, which queues behind any long-running transaction on the table — and every new query queues behind the ALTER.

What to do instead

How Presift flags it

✖ MG002 ERROR  migration.sql:1
    ALTER TABLE users: CONVERT TO CHARACTER SET rebuilds the table and blocks concurrent DML
    Why: Converting a table's character set rewrites every row (the manual lists it as in place, rebuilds table, permits concurrent DML: No); writes are blocked for the duration.
    Do:  Avoid on large/busy tables during traffic. Options: expand/contract (add new structure, migrate data in batches, switch, drop later); an online schema-change tool (gh-ost, pt-online-schema-change); or a maintenance window. Assert the expectation explicitly with ALGORITHM=... so MySQL fails fast if it cannot comply.
    Ref: https://dev.mysql.com/doc/refman/8.0/en/innodb-online-ddl-operations.html

▲ MG003 WARNING  migration.sql:1
    ALTER TABLE users: no ALGORITHM/LOCK clause on a potentially blocking change

Evaluate it on your own migrations — 30 days, whole product, no key to copy

Add the Action to a pull-request workflow and give the job id-token: write. On its first run the client asks GitHub for the job's own identity token and exchanges it, in memory, for a short-lived evaluation entitlement. There is no form, no account, no card and nothing to paste.

name: migration-safety
on: [pull_request]
permissions:
  contents: read
  id-token: write          # lets Presift start your 30-day evaluation
jobs:
  presift:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: nishu-sde/presift@v1
        with:
          paths: db/migrations
          fail-on: error

One 30-day evaluation per GitHub owner — an organisation or a personal account. Linux x86_64 runners with Python 3.9+ (GitHub-hosted ubuntu-* runners qualify). Fork pull requests cannot evaluate, because GitHub issues them no identity token. Outside GitHub Actions the evaluation is not available; a paid organisation key is.

How the evaluation works CI setup and options