← Back to list

TiDB Internals 101: Core Concepts, Raft, Regions, and Partitions

TiDB Internals Concepts

Rurutia1027 · 2026-03-13 17:18 · 0 claps · 7.6 min read
#tidb #raft #sharding #database-sharding #partitioning
Open on Medium ↗

TiDB Internals 101: Core Concepts, Raft, Regions, and Partitions

In Part 1, we discussed why we moved away from application-layer sharding (ShardingSphere, Vitess, and hand-rolled routing) towards TiDB, a distributed SQL database that still speaks the MySQL protocol.

This article is Part 2 of the series. It focuses on the core internal concepts that matter when we run TiDB in a real system, and uses our t_user_coupon table as a concrete example.

TiDB Server (stateless SQL layer)

PD (Placement Driver)

TiKV (distributed KV)

Raft (replication and consistency)

Regions (physical sharding unit)

Partitions (logical sharding at the SQL layer)

The goal is to give you a mental model: enough to reason about behavior, performance, and deployment trade-offs.

The big picture: a distributed database that feels like MySQL

At the API level, TiDB is simple:

  • Clients connect using the MySQL protocol
  • ORMs use a typical MySQL JDBC URL
  • You write SQL and DDL in (almost) normal MySQL syntax.

But under the hood, TiDB is a distributed system. It does not store data in a single process, as a standalone MySQL instance does. Instead, it splits data across multiple nodes, replicates it, and maintains consistency.

The key idea:

From the application’s point of view, there is a single logical database. Underneath, TiDB uses multiple components to provide horizontal scale and fault tolerance.

Those components are:

  • TiDB Server — stateless SQL frontends
  • PD (Placement Driver) — metadata and scheduling brain
  • TiKV — a distributed key-value store that actually holds the data

TiDB Server — stateless SQL layer

What it is:

  • A process that speaks the MySQL protocol.
  • Parses SQL, builds execution plans, coordinates transactions.
  • Does not store user data on the local disk.

Why it matters:

  • Stateless: You can scale TiDB Server horizontally like any other stateless web service.
  • Easy to run behind load balancers, Kubernetes Services, or service meshes.
  • If one TiDB Server crashes, clients reconnect to another; data remains safe in TiKV.

Lifecycle in your head:

Think of TiDB Server as the “SQL brain + coordinator” — for many queries, you can imagine it playing the role that MySQL’s single processor normally plays, except it delegates storage to a distributed backend.

PD (Placement Driver) — cluster metadata and scheduling

What it is

A small set of nodes (usually 3 or 5) that manage cluster-wide metadata:

  • Which TiKV nodes exist
  • How much data/load each has
  • How Regions are distributed

Provides timestamp oracle (TSO) for transactions

Makes decisions about where to place data and when to rebalance

Why it matters

  • PD is the single source of truth for TiKV’s layout
  • When the cluster scales up or down, PD orchestrates Region movement
  • When you add a new TiKV node, PD gradually shifts Regions onto it to balance usage.

PD vs TiKV like control plane vs data plane in K8s

PD vs TiKV like control plane vs data plane in K8s

PD is to TiKV what a control plane is to a data plane: it doesn’t handle every read/write, but it determines how data is laid out and moved.

TiKV — distributed transactional key-value store

What it is:

  • A distributed KV store that stores all user data.
  • Data is stored as key-value pairs with a transactional layer.
  • Implements distributed transactions with MVCC and Two-phase Commit.
  • Uses Raft for replication and leader election.

Why it matters:

This is where TiDB gets:

  • Horizontal scalability (by adding more TiKV nodes).
  • Strong consistency (via Raft)
  • Fault tolerance (data is replicated across nodes)

How it relates to SQL:

At the SQL level, you see rows, tables, and indexes.

Underneath, TiDB maps those to keys and values in TiKV.

For example:

  • Row keys, index keys, etc., are encoded into byte sequences.
  • TiKV stores them and handles transactions on them.

You don’t have to manipulate keys directly, but it’s useful to remember:

Every SQL operation is split into one or more KV operations across TiKV nodes.

Raft — replication and consistency

TiKV nodes don’t store single copies of data. Instead, they use Raft:

Each Region (we’ll define this next) forms a Raft group:

  • 1 leader
  • ≥ 2 followers

Data is accepted only after the Raft group commits the log entry.

Reads can be served by the leader (and in some cases, followers, depending on configuration)

TiDB provides strong consistency guarantees similar to those of a single-node transactional database, but implemented on top of multiple TIKV nodes using Raft.

TiDB provides strong consistency guarantees similar to those of a single-node transactional database, but implemented on top of multiple TIKV nodes using Raft.

Regions — the fundamental sharding unit

Now we get to one of the most important TiDB concepts: the Region.

Definition:

A Region is a small, continuous range of keys in TiKV

Each Region:

  • Has a maximum size (e.g., around 96MB by default)
  • Is replicated via a Raft group.
  • Lives on a subset of TiKV nodes.

Lifecycle of a Region:

  • When a Region grows too large, it splits into two Regions.
  • PD monitors the location and the size of Regions and tells TiKV:
  • To move Regions to other nodes if some TiKV is too hot or too full.

  • To rebalance replicas across racks/regions/zones.

Why Regions matter for sharding:

  • We do not configure “shards” manually.
  • Instead, TiDB + TiKV + PD automatically manages hundreds of thousands of Regions:
  • Regions are the units that move when we add new nodes.

  • Regions are the units PD uses to address hot spots.

Regions are the automatic, fine-grained physical sharding mechanism in TiDB

Regions are the automatic, fine-grained physical sharding mechanism in TiDB

Partitions — logical sharding at the SQL level (with t_user_coupon)

Regions handle physical sharding. But we often need logical sharding too — e.g., “partition this table by user_id so per-user queries prune data efficiently”.

That’s where partitioned tables come in.

In our project, we have a t_user_coupon table:

CREATE TABLE `t_user_coupon` (
    `id`                 varchar(36) NOT NULL COMMENT 'ID',
    `user_id`            bigint(20)  NOT NULL COMMENT 'User ID',
    `coupon_template_id` bigint(20)   DEFAULT NULL COMMENT 'Coupon template ID',
    `receive_time`       datetime     DEFAULT NULL COMMENT 'Receive time',
    `receive_count`      int(3)       DEFAULT NULL COMMENT 'Receive count',
    `valid_start_time`   datetime     DEFAULT NULL COMMENT 'Validity start time',
    `valid_end_time`     datetime     DEFAULT NULL COMMENT 'Validity end time',
    `use_time`           datetime     DEFAULT NULL COMMENT 'Use time',
    `source`             tinyint(1)   DEFAULT NULL COMMENT 'Source 0: center 1: platform 2: shop',
    `status`             tinyint(1)   DEFAULT NULL COMMENT 'Status 0: unused 1: locked 2: used 3: expired 4: revoked',
    `create_time`        datetime     DEFAULT NULL COMMENT 'Created time',
    `update_time`        datetime     DEFAULT NULL COMMENT 'Updated time',
    `del_flag`           tinyint(1)   DEFAULT NULL COMMENT 'Delete flag 0: not deleted 1: deleted',
    `CREATED_DATE`       datetime     DEFAULT NULL,
    `MODIFIED_DATE`      datetime     DEFAULT NULL,
    `DELETED`            varchar(36)  DEFAULT NULL,
    `VERSION_NUMBER`     bigint(20)   DEFAULT 1,
    `LOCKED`             bit(1)       DEFAULT b'0',
    `IS_DISABLED`        bit(1)       DEFAULT b'0',
    `IS_OUT_OF_SYNC`     bit(1)       DEFAULT b'0',
    `entity_tag`         varchar(255) DEFAULT NULL,
    PRIMARY KEY (`id`, `user_id`),
    UNIQUE KEY `idx_user_id_coupon_template_receive_count` (`user_id`,`coupon_template_id`,`receive_count`),
    KEY `idx_user_id` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='User coupon table'
  PARTITION BY HASH(`user_id`) PARTITIONS 32;

Important rules:

In MySQL/TiDB partitioning:

  • The primary key and unique keys must include the partition key (user_id).
  • Partition key columns should be **NOT NULL**

What TiDB does with partitions

At logical level:

The table is split into 32 partitions based on HASH(user_id)

At physical level:

Each partition consists of one or more Regions.

Those Regions are distributed and replicated across TiKV nodes by PD and Raft.

t_user_coupon (logical table)

PARTITION p0 : user_id hash in bucket 0 ---> multiple Regions 
PARTITION p1 : user_id hash in bucket 1 ---> multiple Regions 
...
PARTITION p31 : user_id hash in bucket 31 ---> multiple Regions 

Each Region is a Raft group across TiKV nodes:

p9:
Region A: [some key range], leader on TiKV-1, followers on TiKV-2/TiKV-3
Region B: ...

When we run:

SELECT * from t_user_coupon WHERE user_id = 1001; 

TiDB’s optimizer applies partition pruning:

  • It computes which partition(s) HASH(1001) maps to, say p9.
  • It only scans Regions belonging to p9.
  • That’s why in an **EXPLAIN** we might see something like:
TableFullScan_7, ..., table: t_user_coupon, partition:p9, ...

This is concrete evidence that:

  • The query only touches partition p9, not all 32 partitions.
  • Physical IO is limited to Regions underneath that partition.

If we forget to include user_id (the sharding key)In the query predicate (or when the optimizer can’t infer it), TiDB cannot prune partitions and may scan more partitions, even the whole partitions (resulting in IO-intensive and low efficiency).

That’s why in our HQL + sharding layer, we enforce:

Every query to a sharded table must include the sharding key (e.g., userId)

We want to guarantee opportunities for partition pruning.

Distributed systems vocabulary: mapping TiDB

Here is a quick mapping between common distributed systems terms and TiDB

  • Cluster: The whole TiDB deployment (TiDB Server + PD + TiKV + optional TiFlash)
  • Node: an individual process/pod (TiDB node, Pod node, TiKV node)
  • Store: a TiKV node (storage node), holding multiple Regions
  • Region: a small key range; unit of data distribution & Raft replication
  • Shard: conceptually similar to “set of data”; in TiDB, realized as many Regions
  • Replica: a copy of a Region (leader or follower) stored on a TiKV node
  • Leader: the Raft leader for a Region; handles writes & often reads
  • Follower: Raft follower for a Region; replicates the log, can serve some reads
  • Partition: logical split of a SQL table (e.g., PARTITION BY HASH(user_id)); each partition is backed by one or more Regions.

Mentally:

If you are used to “shards” in traditional systems, think “a shard = many Regions

If you are used to partitions in relational databases, think “a partition = a logical shard”, backed by many physical regions.

Why are these internal matters in practice (with t_user_coupon)

We don’t have to become a distributed systems engineer to use TiDB effectively, but understanding these building blocks helps you:

Design schemas that play well with partitioning:

  • Choose good partition keys ( user_id for t_user_coupon, shop_number for coupon templates, etc.).
  • Respect primary key + partition key rules

Write queries that enable partition pruning:

  • Always include the partition/sharding key in predicates (WHERE user_id= ?).
  • Avoid cross-partition joins and “no key” scans for hot tables.

Reason about performance:

  • Hot keys -> hot Regions -> PD may move them, but schema changes might still be needed.
  • Skewed traffic on certain users or tenants can produce hotspots.

Operate cluster confidently:

  • When we add TiKV nodes, Regions will rebalance automatically.
  • If a TiKV node fails, Raft and PD handle failover and data re-distribution.

For our t_user_coupon table specifically:

  • We know partitioning is by user_id
  • We enforce that all sharded queries include userId in the application (HQL + ShardingContext).
  • We can see, via EXPLAIN`, that TiDB prunes down to a single partition (and thus a subset of Regions).

In later parts, we’ll connect these internals to:

  • Concrete deployment stories (TiDB Operator on Kubernetes, kind, Docker)
  • Observability patterns (traces, logs, metrics) for TiDB-backed microservices.
  • Best practices and pitfalls when combining TiDB with ORMs like Hibernate.

For now, the key mental model is:

TiDB presents one logical MySQL-compatible database. Underneath, it shards data into Regions, stores them in TiKV, coordinates via PD, and lets you control logical sharding using partitioned tables like t_user_coupon.

References


메타데이터
post_id
acd760cbe0d4
slug
tidb-internals-101-acd760cbe0d4
url
https://medium.com/@rurutia1027/tidb-internals-101-acd760cbe0d4
canonical_url
https://medium.com/@rurutia1027/tidb-internals-101-acd760cbe0d4
author_url
https://medium.com/@rurutia1027
status
ok
fetched_at
2026-07-12 00:22:36