Copy of Blog - Feature

Key Takeaways

  • Your ORM assumes one database with real transactions. Sharded MySQL quietly breaks that assumption.
  • Cross-shard writes turn one ORM transaction into several, and ACID does not span them.
  • The failures are silent: Partial writes, phantom state, and bugs you cannot reproduce.
  • Distributed SQL restores the single-database contract, so the ORM’s assumptions hold again.

If you have ever watched an ORM-heavy application meet a sharded MySQL backend, you know the moment I mean. The code looks right. The tests pass. Then production traffic arrives, and you start seeing the impossible: An order without its line items, a user whose profile says one thing and whose billing record says another, a job marked complete that never ran. Nobody changed the code. The database changed shape underneath it.

I see this in the field whenever a team scales MySQL by sharding, whether hand-rolled or through a proxy layer. The application was written against a promise: One database, real transactions, what you commit is what you read. The ORM was built on that promise too. Sharding quietly revokes it, and neither your code nor your ORM gets a memo.

The Contract Your ORM Signed

Every mainstream ORM, whether it is Hibernate, Django ORM, ActiveRecord, Prisma, or SQLAlchemy, is built on the same handshake with the database. Open a session. Make several changes. Commit, and either everything lands or nothing does. Read your own writes immediately. That handshake is ACID: Atomicity, consistency, isolation, durability.

The ORM leans on it everywhere, in ways you stop noticing. A save() that touches a parent row and three child rows. A unit-of-work that flushes a dozen dirty objects in one commit. Lazy loading that assumes the object graph it is walking is a consistent snapshot. Optimistic locking that assumes a version check and an update happen atomically.

On a single MySQL instance, InnoDB keeps that promise, and everything works. The problems start when one database becomes several and pretends it did not.

Where Sharded MySQL Breaks the Handshake

Shard MySQL by customer, by region, by whatever key you chose, and the promise fractures along the shard boundary:

One ORM sharded MySQL commit stays atomic on a single instance; split across shards, a failed child write leaves an orphaned order.

Figure 1. One ORM commit stays atomic on a single instance; split across shards, a failed child write leaves an orphaned order.

  • One transaction becomes many. When the parent row lives on shard A and a child row lands on shard B, your ORM’s single commit() is now two commits on two databases. If the second fails after the first succeeds, you have a partial write. The ORM reports success or failure; it has no vocabulary for “half.”
  • Isolation stops at the shard edge. Two transactions on different shards do not see each other’s locks or snapshots. Invariants your code enforces across entities, unique constraints, balance checks, and foreign keys become best-effort suggestions the moment the entities land on different shards.
  • Read-your-writes gets probabilistic. Add read replicas per shard, which every sharded setup does, and the ORM’s assumption that a read after a write sees the write now depends on replication lag. The bug reproduces only under load, on Tuesdays.
  • The ORM’s query model shrinks. Joins, aggregates, and transactions across shards either fail, silently return partial results through the proxy, or get rewritten as application code. Your data layer migrates upward into your service layer, one workaround at a time.

The system does not fail loudly. It fails quietly, in the gap between what your ORM assumes and what your topology delivers. In distributed systems, boring is the highest compliment, and sharded MySQL under an ORM is never boring.

The Fix is Not a Smarter ORM

Teams try to patch this at the application layer: saga patterns, two-phase commit libraries, outbox tables, “eventual consistency” wrappers around code that was written to be immediate. All of it works, in the sense that a hand-built distributed transaction layer works. All of it is also your team maintaining distributed-systems machinery that a database should be providing, forever, on every feature.

The cleaner fix is to give the ORM back the database it was promised: One logical database that speaks MySQL and provides ACID across all of it, regardless of where the data physically lives.

That is the category 티DB lives in. To your ORM, it is MySQL: Same wire protocol, same drivers, same commit(). Underneath, a stateless SQL layer plans queries across a distributed storage layer, TiKV, which shards data automatically into ranges, replicates it with the Raft consensus protocol, and runs distributed transactions with two-phase commit inside the database. Your parent row and child rows may live on different nodes. Your ORM neither knows nor cares. The commit is atomic across all of them, isolation holds cluster-wide, and a read after a write sees the write.

The sharding still happens. It just happens below the SQL line, where it belongs, instead of above it, where your ORM can trip over it.

The Honest Edge

Distributed ACID is not free, and I will not pretend it is. Cross-node transactions pay a coordination cost that a single InnoDB instance does not, so a hot single-row workload on one machine will always beat a distributed commit on raw latency. A few MySQL edge behaviors differ, and some ORM-generated query patterns benefit from a look at the execution plan once you are distributed.

But compare the honest alternatives. A single MySQL instance keeps perfect ACID until you outgrow it, and then you are sharding. Sharded MySQL scales and hands the ACID problem to your application. Distributed SQL keeps the contract and moves the coordination cost into the database, where it is engineered once instead of re-invented per team. For an application that has already outgrown one box, that is the trade that keeps your codebase honest.

GuaranteeSingle MySQLSharded MySQLDistributed SQL (TiDB)
Atomic multi-row commitYesOnly within a shardYes, cluster-wide
Cross-entity isolationYesBreaks across shardsYes, cluster-wide
Read-your-writesYesLag-dependentYes
Cross-shard joinsN/A (one node)Application codeNative SQL
Who maintains shardingNobody (until you outgrow it)Your team, foreverThe database
Scales writesNoYesYes

The Takeaway

Here is the mental model to keep. Your ORM is a contract lawyer for a contract your sharded database stopped honoring. You can renegotiate every clause in application code, or you can restore the contract. If your MySQL workload has outgrown one instance and your codebase is built on an ORM, a distributed SQL database that speaks MySQL is the path that scales without rewriting what your code believes about transactions.

See what this looks like on a real workload. Plaid moved 234 databases and a large ORM-backed codebase to TiDB with a six-person team, keeping the MySQL wire protocol and their existing transactional SQL. Read the Plaid migration story.

자주 묻는 질문

Do ORMs work with sharded MySQL?

Partially. ORMs connect and run single-shard queries fine, but their transaction, join, and consistency features assume one database. Cross-shard operations break atomicity and isolation guarantees the ORM silently relies on, producing partial writes and inconsistent reads.

What is ACID and why does it matter at scale?

ACID stands for atomicity, consistency, isolation, and durability: the guarantees that grouped changes land together, invariants hold, concurrent work does not interleave incorrectly, and committed data survives failure. At scale the question is whether those guarantees span your whole dataset or stop at a shard boundary.

Does TiDB support ACID transactions across nodes?

Yes. TiDB provides distributed ACID transactions using two-phase commit over the Raft-replicated TiKV storage layer, so a single transaction can atomically modify rows on different nodes, with snapshot isolation cluster-wide.

Can I keep my ORM if I migrate from MySQL to TiDB?

Yes. TiDB speaks the MySQL wire protocol, so Hibernate, Django ORM, ActiveRecord, Prisma, SQLAlchemy, and other MySQL-compatible ORMs connect with existing drivers and continue issuing the same transactional SQL.

Is there a performance cost to distributed transactions?

Yes, cross-node commits pay a coordination cost that single-instance InnoDB does not. The comparison that matters is against sharded MySQL, where that cost does not disappear but moves into application code your team maintains.


Experience modern data infrastructure firsthand.

무료로 시작하세요

Have questions? Let us know how we can help.

문의하기

TiDB Cloud 전용

A fully-managed cloud DBaaS for predictable workloads

TiDB Cloud 스타터

A fully-managed cloud DBaaS for auto-scaling workloads