giip
SES Proposal
TiDBExpert Review Required移行バージョン互換性インデックストランザクションサイジング

Checklist for Migrating from TiDB to Aurora MySQL

Published 2026-08-13 · Updated 2026-08-13 · Last Verified 2026-08-13

Answer

When migrating from TiDB to Aurora MySQL, do not assume "it's MySQL-compatible, so it will just work." Instead, verify seven things in your actual environment: ID generation (`AUTO_INCREMENT`'s non-sequential allocation and `AUTO_RANDOM`), primary key structure (clustered vs. non-clustered, `SHARD_ROW_ID_BITS`), TiDB-specific syntax and system variables, transaction behavior, statistics and index selection, character set and collation, and capacity (TiKV and InnoDB require different amounts). Since behavior changes across TiDB versions, this assumes you verify against your own environment's version rather than this article.

Applicability of This Document

ProductTiDB (source) → Aurora MySQL (target)
Verified VersionsTiDB behavior varies significantly by version, so always run `SELECT TIDB_VERSION();` to check your environment's version before verifying each item. Assumes the target is Aurora MySQL 3.x (MySQL 8.0-compatible)
EnvironmentTiDB (self-hosted / managed) → Amazon Aurora (AWS)
Required PermissionsInvestigation requires read access to `information_schema` and `SELECT` on the target schema. Running the migration requires read access on the dump source and write access on the target
Execution ImpactNo impact from the investigation SQL. The initial load and CDC setup put load on both the source and target
RestartNot required for investigation. Cutover downtime depends on the method chosen
Last Verified2026-08-13

Ready-to-Run Commands

Check the source TiDB's version and key settingsRead-only
対象
TiDB (all versions)
権限
Connection privilege
変更作業
None (read-only)
Production実行
Possible
-- 対象: TiDB(バージョンにより出力が異なる)
-- 権限: 接続権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能

-- 1) TiDB のバージョン(VERSION() はMySQL互換の文字列、TIDB_VERSION() はTiDB固有の詳細)
SELECT VERSION() AS mysql_compat_version;
SELECT TIDB_VERSION() AS tidb_version;

-- 2) トランザクションモードと分離レベル
SHOW GLOBAL VARIABLES WHERE Variable_name IN (
    'tidb_txn_mode',
    'transaction_isolation',
    'tidb_constraint_check_in_place',
    'tidb_enable_clustered_index'
);

-- 3) 新しい照合順序フレームワークが有効かどうか
--    (無効な環境では utf8mb4_general_ci の比較挙動がMySQLと異なる)
SELECT VARIABLE_NAME, VARIABLE_VALUE
FROM mysql.tidb
WHERE VARIABLE_NAME = 'new_collation_enabled';

The version obtained here is the premise for every decision that follows. Since TiDB's defaults and supported features change across versions, prefer your own environment's output whenever it conflicts with this article. `mysql.tidb` or `tidb_enable_clustered_index` may not exist in some versions (if you get an error, you can conclude that version simply lacks the feature).

Find TiDB-specific attributes from table definitionsRead-only
対象
TiDB (all versions)
権限
Metadata read privilege on the target schema
変更作業
None (read-only)
Production実行
Possible
-- 対象: TiDB(全バージョン)
-- 権限: 対象スキーマのメタデータ参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能

-- 1) 定義そのものを出力し、AUTO_RANDOM / SHARD_ROW_ID_BITS /
--    CLUSTERED・NONCLUSTERED / PRE_SPLIT_REGIONS の有無を目視で確認する
SHOW CREATE TABLE SampleDB.sample_table;

-- 2) 主キーの構造を一覧で確認する(TIDB_PK_TYPE はTiDB独自列。
--    存在しない版ではエラーになるので、その場合は 1) を全テーブル分実行する)
SELECT TABLE_SCHEMA, TABLE_NAME, TIDB_PK_TYPE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'metrics_schema', 'sys')
ORDER BY TABLE_SCHEMA, TABLE_NAME;

-- 3) 主キーの無いテーブル(移行後のCDCで問題になる)
SELECT t.TABLE_SCHEMA, t.TABLE_NAME
FROM information_schema.TABLES t
LEFT JOIN information_schema.KEY_COLUMN_USAGE k
       ON  k.TABLE_SCHEMA    = t.TABLE_SCHEMA
       AND k.TABLE_NAME      = t.TABLE_NAME
       AND k.CONSTRAINT_NAME = 'PRIMARY'
WHERE t.TABLE_TYPE = 'BASE TABLE'
  AND t.TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'metrics_schema', 'sys')
  AND k.COLUMN_NAME IS NULL
ORDER BY t.TABLE_SCHEMA, t.TABLE_NAME;

`AUTO_RANDOM` is specific to TiDB and has no MySQL equivalent. A column using it needs to be replaced with a different design on the Aurora MySQL side (a sequential `BIGINT`, application-side ID generation, a UUID scheme, etc.) — consider both value compatibility and digit count. `SHARD_ROW_ID_BITS` and `PRE_SPLIT_REGIONS` are settings for TiKV's distributed placement and have no equivalent concept on Aurora (this doesn't mean you can simply ignore them — consider what happens after migration to the access pattern that needed that setting).

Check usage of foreign keys, generated columns, and partitionsRead-only
対象
TiDB (all versions)
権限
Metadata read privilege on the target schema
変更作業
None (read-only)
Production実行
Possible
-- 対象: TiDB(全バージョン)
-- 権限: 対象スキーマのメタデータ参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能

-- 1) 外部キー定義の有無(定義があっても実際に強制されているかは版に依存する)
SELECT CONSTRAINT_SCHEMA, TABLE_NAME, CONSTRAINT_NAME,
       REFERENCED_TABLE_NAME, UPDATE_RULE, DELETE_RULE
FROM information_schema.REFERENTIAL_CONSTRAINTS
ORDER BY CONSTRAINT_SCHEMA, TABLE_NAME;

-- 2) 生成列(GENERATED COLUMN)
SELECT TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME, EXTRA, GENERATION_EXPRESSION
FROM information_schema.COLUMNS
WHERE GENERATION_EXPRESSION IS NOT NULL
  AND GENERATION_EXPRESSION <> ''
ORDER BY TABLE_SCHEMA, TABLE_NAME;

-- 3) パーティション定義
SELECT TABLE_SCHEMA, TABLE_NAME, PARTITION_NAME, PARTITION_METHOD, PARTITION_EXPRESSION
FROM information_schema.PARTITIONS
WHERE PARTITION_NAME IS NOT NULL
ORDER BY TABLE_SCHEMA, TABLE_NAME, PARTITION_ORDINAL_POSITION;

TiDB has, for a long time, accepted foreign key syntax without actually enforcing the constraint. Since whether it's enforced depends on the version, check the real behavior in your environment by trying a violating INSERT rather than just checking whether a definition exists. If it was not enforced before, data inserts that previously succeeded may start failing once foreign keys are enforced on the Aurora MySQL side.

Measure the data volume to migrate (don't use it as-is to size the target)Read-only
対象
TiDB (all versions)
権限
Read access to `information_schema`
変更作業
None (read-only)
Production実行
Possible
-- 対象: TiDB(全バージョン)
-- 権限: information_schema の参照権限
-- 変更作業: なし(参照のみ)
-- Production 実行: 可能
SELECT
    TABLE_SCHEMA,
    TABLE_NAME,
    TABLE_ROWS                                            AS estimated_rows,
    ROUND(DATA_LENGTH  / 1024 / 1024 / 1024, 2)           AS data_gb,
    ROUND(INDEX_LENGTH / 1024 / 1024 / 1024, 2)           AS index_gb,
    TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_TYPE = 'BASE TABLE'
  AND TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'metrics_schema', 'sys')
ORDER BY (DATA_LENGTH + INDEX_LENGTH) DESC;

TiDB's `TABLE_ROWS` and `DATA_LENGTH` are estimates based on statistics. Since TiKV keeps multiple replicas and also compresses data, you cannot use this value as-is for Aurora's (InnoDB's) required storage. Estimate the target capacity from the actual ratio measured by loading representative tables.

Produce a dump for the initial loadMedium
対象
TiDB (Dumpling)
権限
`SELECT` on the dump target schema (TiDB side)
変更作業
None (source is read-only), but it adds read load
Production実行
Carry out during a window that can tolerate the load
# 対象: TiDB(Dumpling によるダンプ)
# 権限: ダンプ対象スキーマへの SELECT(TiDB側)
# 変更作業: なし(移行元は参照のみ)。ただし読み取り負荷がかかる
# Production 実行: 負荷を許容できる時間帯で実施すること

# まず1テーブルだけダンプして所要時間と出力サイズを実測する
tiup dumpling \
  --host 192.0.2.10 \
  --port 4000 \
  --user sample_user \
  --filetype sql \
  --threads 8 \
  --rows 200000 \
  --filter 'SampleDB.sample_table' \
  --output /var/tmp/dump-sample

# 出力サイズと所要時間を確認する(この実測値だけが計画の根拠になる)
du -sh /var/tmp/dump-sample

Measure with a few tables first, then extrapolate to the whole. Specifying `--rows` splits a table for parallel output. Raising `--threads` increases load on the source, so start low while in production. Option names can change between Dumpling versions, so check with `tiup dumpling --help`.

Plan the change-data-capture (CDC) setupHigh
対象
TiCDC (TiDB side) or AWS DMS
権限
Operational privileges on TiCDC, or DMS IAM privileges and endpoint credentials
変更作業
Yes (configures change data delivery; affects both source and target)
Production実行
A configuration change on the production source. Pre-verification and a rollback procedure are mandatory
# 対象: TiCDC(TiDB側)または AWS DMS
# 権限: TiCDC の操作権限、または DMS の IAM 権限とエンドポイント資格情報
# 変更作業: あり(変更データ配信の構成)
# Production 実行: 本番ソースへの設定変更。事前検証と切り戻し手順を用意してから実施

# TiCDC で MySQL 互換のシンク(= Aurora MySQL)へ変更を流す例。
# CLI のオプション名はTiDB/TiCDCのバージョンで変わる(--pd と --server など)ため、
# 必ず自環境のバージョンのドキュメントで確認すること。
tiup ctl cdc changefeed create \
  --server "http://192.0.2.10:8300" \
  --changefeed-id "example-changefeed" \
  --sink-uri "mysql://sample_user@example-rds-endpoint:3306/"

# 作成後は状態と遅延を確認する
tiup ctl cdc changefeed list --server "http://192.0.2.10:8300"

The TiCDC CLI's option names have changed across versions (e.g., `--pd` to `--server`). Don't use the exact form shown here — match it to your own environment's version documentation. If using AWS DMS against a source TiDB, check with the actual DMS version you'll use whether TiDB is supported as a source and which mode (full-load only / including CDC) is available (this article does not state this definitively). Don't write the password directly on the command line — use an environment variable or a config file.

How to Read the Results

ColumnMeaningWhat to Check
tidb_versionTiDB's actual versionThe premise for every compatibility decision. Prefer your own environment's version over this article
tidb_txn_modeTransaction mode (optimistic / pessimistic)If optimistic, the app may be written assuming a conflict error is returned at commit time
new_collation_enabledWhether the new collation framework is enabledIf disabled, comparison behavior for utf8mb4-family collations differs from MySQL. Duplicate detection may change after migration
TIDB_PK_TYPEWhether the primary key is clusteredPerformance characteristics assumed under clustering are not guaranteed to be reproduced on Aurora
estimated_rowsEstimated row count based on statisticsNot an exact count. Cross-check against a verification `COUNT(*)`
data_gb / index_gbData and index size as reported by TiDBIncludes TiKV replication and compression, so it can't be used as-is for Aurora's required capacity
REFERENCED_TABLE_NAMEWhat a foreign key referencesCheck whether it is actually enforced by testing, not just whether a definition exists
GENERATION_EXPRESSIONExpression for a generated columnCheck individually whether function support matches on the target

When to Use This

  • SQL that worked on TiDB produces an error in the Aurora MySQL test environment
  • Continuity of ID generation changes after migration, conflicting with application assumptions
  • The same index exists, but only after migration does the execution plan change and slow down
  • Data that violates a foreign key already exists and cannot be loaded into the target
  • The target's storage estimate diverges significantly from the source's reported value
  • String comparison or sorting results changed before and after migration

Possible Causes (Most Likely First)

  1. 01

    `AUTO_INCREMENT` allocation works differently

    Because TiDB allocates ID ranges in bulk to each node, IDs can be non-sequential. An application that assumes "higher ID = later insertion order" needs re-review regardless of which side it runs on. Since the exact behavior depends on version and configuration, measure sequentiality in your own environment.

  2. 02

    MySQL has no equivalent of `AUTO_RANDOM`

    This is a TiDB-specific feature for avoiding hotspots. When migrating to Aurora MySQL, the value-generation scheme itself needs to be redesigned. Also check whether existing ID values can be carried over as-is.

  3. 03

    The clustered-primary-key assumption differs

    InnoDB is clustered by the primary key by default, while TiDB lets you choose clustered or non-clustered. A non-clustered table's per-access-pattern performance characteristics change after migration.

  4. 04

    Transaction behavior differs

    Optimistic transactions detect conflicts at commit time, while pessimistic transactions take locks at execution time. Which one was in use changes how lock waits and errors manifest after migration.

  5. 05

    TiDB-specific syntax, system variables, or hints are in use

    System variables starting with `TIDB_`, TiDB-specific optimizer hints, and `ADMIN`-family administrative commands don't work on MySQL. Full-text search the application and batch SQL to find them.

  6. 06

    The statistics and index selection mechanism differs

    Since the optimizer is a different implementation, the execution plan chosen can differ even with the same index configuration. Treat "the same SQL is now slow" after migration as expected, and plan to re-verify execution plans for representative queries on the target.

  7. 07

    The storage structure differs

    TiKV keeps replicas and also compresses data. Since the assumptions differ from InnoDB, you cannot mechanically convert the source's usage into the target's required capacity.

Diagnostic Steps

  1. 1

    Retrieve TiDB's version and key settings

    Read-only

    Check `TIDB_VERSION()`, `tidb_txn_mode`, and the state of the collation framework. Every subsequent decision is premised on this result.

  2. 2

    Save `SHOW CREATE TABLE` for every table

    Read-only

    Some TiDB-specific attributes appear only in the definition statement. Save all of them and search for `AUTO_RANDOM` / `SHARD_ROW_ID_BITS` / `NONCLUSTERED`.

  3. 3

    Full-text search the application SQL for TiDB-specific elements

    Read-only

    Search for `TIDB_`, custom hints, and `ADMIN` commands. These aren't visible from the DB side, so they need to be found in the code.

  4. 4

    Test in a verification environment whether foreign keys are actually enforced

    Medium

    Run a violating INSERT and check whether it errors. This cannot be determined from the definition alone.

  5. 5

    Test-load a representative table on the target and measure the capacity ratio

    Medium

    This measured value alone is the basis for estimating the target's storage.

  6. 6

    Run representative queries on the target and compare execution plans and timing

    Medium

    There is no guarantee of the same performance as the source. Include time in the plan to handle queries that show a difference individually.

Solutions

Low-risk action that can be done immediately

  • Pin down the version and list the differences

    Read-only

    Judge based on "this specific version of TiDB," not "TiDB" in general. The list of differences becomes the backbone of the migration plan.

  • Separate what will and will not be migrated

    Read-only

    If temporary tables or large analytical tables can be excluded from migration, the burden of the initial load drops significantly.

Change requiring advance review

  • Replace the design of `AUTO_RANDOM` columns

    High

    Decide on the target-side ID-generation scheme (sequential, application-generated, UUID-based) and check whether existing values can be carried over and whether the digit count fits application assumptions. Involves application-side changes.

  • Provision keys for tables with no primary key

    High

    When synchronizing differences via CDC, a table with no primary key causes apply errors. Define a key before migration.

  • Re-verify execution plans for representative queries on the target

    Medium

    Reserve a verification period in the plan on the assumption that indexes will need to be added or changed on the target.

  • Standardize the character set and collation to the target's baseline

    Medium

    Collation differences change comparison results. See the related article for utf8mb4 migration checks.

Change involving a restart or service impact

  • Carry out the initial load

    High

    Dump with Dumpling or similar and load it into the target. Always estimate the duration from a sample measurement.

  • Set up change data capture (TiCDC / DMS)

    High

    This is a configuration addition on the production source. Decide how lag will be monitored and the rollback procedure before carrying this out.

Work requiring expert review

  • Carry out the cutover

    Expert Review Required

    Decide the order and ownership of stopping writes, confirming the difference has caught up, verifying consistency, switching the connection target, and the rollback decision, before carrying it out. This is an area driven by pre-agreed procedure and human judgment, not automation.

!Warnings

  • TiDB's behavior varies by version. Whenever this article's description conflicts with your own environment's output, always prefer your environment's output.
  • "MySQL-compatible" does not mean "identical." Syntax being accepted is a different matter from producing the same result and the same performance.
  • Do not convert the source's `DATA_LENGTH` directly into Aurora's required storage. TiKV's value assumes replicas and compression.
  • A foreign key may not be enforced even if it is defined. If it becomes enforced on the target, existing data loading or existing processing can start failing.
  • This article does not give a duration for the migration. Since it depends on table composition, data volume, network, and parallelism, always estimate it from a sample measurement.
  • Cutover is a hard-to-reverse operation. Define the point of no return beforehand and decide who makes the call before carrying it out.

Differences by Version and Environment

Differences across TiDB versionsThe default for clustered primary keys, the collation framework, foreign key enforcement, and TiCDC CLI options all vary by version. Avoid definitive statements and refer to the official documentation matching the result of `SELECT TIDB_VERSION();`.
When the target is Aurora MySQL 3.x (MySQL 8.0-compatible)Since the default collation becomes a `utf8mb4_0900_ai_ci`-family collation, comparison behavior can differ from the source's collation. Verify that duplicate detection does not change on columns with a unique constraint.
When the target is Aurora MySQL 2.x (MySQL 5.7-compatible)If syntax added in MySQL 8.0 (window functions, CTEs, etc.) was used on the TiDB side, it will not work on the target. A full SQL inventory is needed.

If This Doesn't Resolve It

  • Check the application's driver and timeout settings

    Changing the connection target can change reconnection and timeout behavior.

  • Decide where analytical workloads go

    If analytical queries were co-located on TiDB, Aurora alone may not provide the same performance characteristics. Consider a read replica or a separate platform.

  • Re-measure batch processing parallelism and duration

    Since the storage structure changes, the same degree of parallelism is not guaranteed to be optimal.

  • Rebuild operational procedures (backup, monitoring, privilege management) for the target

    TiDB-specific procedures cannot be used as-is. Include creating operational procedures in the migration plan.

  • Check the conditions and procedure for rolling back

    Document, before the cutover, how far back you can roll back and what gets discarded if you do.

Basis and Limitations of This Document

General technical explanation

Based on the publicly documented differences between TiDB and MySQL (Aurora MySQL) and general verification practices for cross-engine database migration. Since TiDB's behavior varies significantly by version, this article shows what to check rather than asserting any specific behavior. It does not include any specific customer's migration case or actual duration figures.

FAQ

TiDB is MySQL-compatible, so can it be migrated as-is?

Not necessarily. What's compatible is the connection protocol and most SQL syntax; ID generation behavior, primary key structure, transaction behavior, statistics and index selection, and storage assumptions all differ. Treat syntax being accepted as separate from getting the same result and the same performance, and verify each item individually.

What should be done about columns using AUTO_RANDOM?

Since MySQL has no equivalent feature, the ID-generation scheme itself needs to be redesigned. Decide whether to use sequential IDs, application-side generation, or a UUID scheme, and check whether existing ID values can be carried over as-is and whether the digit count fits application assumptions.

How much storage is needed on the target?

It cannot be determined from the source's reported value. Since TiKV keeps replicas and also compresses data, its assumptions differ from InnoDB's. Actually load representative tables into the target and estimate the total from that ratio.

Can this be run in production?

All the investigation SQL is read-only and can be run on a production TiDB. A Dumpling dump adds read load and needs a scheduled window; configuring TiCDC or DMS is a configuration change on the production source. Carry out the cutover following a pre-agreed procedure.

What happens to foreign keys?

On TiDB, a foreign key may be defined but not actually enforced. Since whether it's enforced depends on the version, insert violating data to check the actual behavior. If it was not enforced, existing processing may start failing once foreign keys become active on the target.

How should the results be interpreted?

Classify each checklist item into one of three categories: "no difference," "needs an application change," or "needs a design change." If there is even one item requiring a design change, the migration becomes a project that includes application modification, not just a data move. Build the schedule on that premise.

Questions This Document Covers

  • How to check index differences between MySQL-compatible databases
  • Want to know why AUTO_INCREMENT is not sequential in TiDB
  • Data volume estimation when migrating from TiDB to RDS
  • Does a TiDB foreign key behave the same as in MySQL

What the Risk Labels Mean

  • Read-onlyDoes not change data or settings.
  • LowImpact is limited, but permissions and load should be checked.
  • MediumMay affect performance, locking, or cost.
  • HighMay cause an outage, data loss, or require recovery work.
  • Expert Review RequiredRequires a separate review before applying to production.

GIIP's Scope of Support

The migration decision itself can proceed just by filling out this article's checklist in your own environment. What's burdensome is the period after cutover spent continuously catching "problems that didn't show up on the source." For a period after cutover, GIIP tracks the execution time, execution plan, and error rate of representative queries alongside their pre-migration values, isolating only the ones that show degradation as something to act on. The migration work itself is decided by a person, while the ongoing comparison and initial investigation afterward are handled by an AI agent.

Author & Technical Review

GIIP Production Operations Team

About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.

Related Knowledge

Related Services

Request a migration assessment from TiDB

If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.

Request a migration assessment from TiDB

← Back to Knowledge Base