How BEGIN CONCURRENT Enables Multi-Version Concurrency Control in Turso
BEGIN CONCURRENT creates snapshot-based MVCC transactions that allow multiple writers to execute simultaneously without exclusive locks, detecting conflicts at commit time through row versioning.
Turso's BEGIN CONCURRENT statement activates the database's multi-version concurrency control (MVCC) engine, enabling high-throughput scenarios where multiple connections can write concurrently without blocking each other. According to the tursodatabase/turso source code, this transaction mode replaces traditional exclusive write locks with snapshot isolation and optimistic conflict detection.
Parsing and Transaction Type Detection
The SQL parser recognizes BEGIN CONCURRENT in parser/src/parser.rs (lines 53,08-53,12) and tags the statement with TransactionType::Concurrent. This classification triggers the VDBE (Virtual Database Engine) to follow the MVCC code path rather than the classic WAL exclusive-lock path.
When the VDBE executes this opcode in core/vdbe/execute.rs (lines 55,500-55,560), it calls begin_mvcc_tx to initialize the MVCC transaction state.
Allocating Transaction IDs Without Write Locks
Unlike standard transactions that acquire exclusive write locks, BEGIN CON CURRENT creates a snapshot-based transaction by allocating a new transaction ID in the MVCC store (MvStore). The connection records this ID via conn.set_mv_tx_for_db, allowing the transaction to proceed without blocking other writers.
This approach enables multiple connections to hold write transactions simultaneously, with each working on its own logical version of the database.
Pinning Consistent WAL Snapshots
To ensure read consistency, the pager executes begin_read_tx() followed by mvcc_refresh_if_db_changed() when the transaction starts. This pins a consistent WAL (Write-Ahead Log) snapshot so that all reads within the transaction see the same database state, even while other writers commit changes.
This mechanism eliminates non-repeatable reads and dirty reads, providing snapshot isolation for the duration of the transaction.
Versioning Rows and Detecting Conflicts
Each writer operates on its own version of rows. When a write attempt occurs, the MVCC layer checks whether the target row version is visible to the current transaction. As documented in core/mvcc/mod.rs (lines 9-25), if another concurrent transaction has already written a newer version, the later transaction receives a LimboError::Busy error and must retry or abort.
This "dirty write" detection prevents lost updates by ensuring transactions only modify rows they have isolated access to.
Commit-Time Validation and First-Writer-Wins
Conflict detection culminates at commit time. The commit_tx_no_conn helper in core/mvcc/database validates that no write-write conflicts occurred during the transaction. If a conflict is detected—meaning another transaction committed changes to the same rows—the later transaction is rolled back.
This enforces a first-writer-wins policy, ensuring that only the first concurrent transaction to commit successfully persists its changes, while conflicting transactions must retry.
Using BEGIN CONCURRENT in Practice
You can leverage BEGIN CONCURRENT through SQL commands or programmatic APIs.
SQL Example
-- Connection A
BEGIN CONCURRENT;
INSERT INTO notes (title, body) VALUES ('A', 'first');
COMMIT;
-- Connection B (runs concurrently)
BEGIN CONCURRENT;
INSERT INTO notes (title, body) VALUES ('B', 'second');
COMMIT;
Rust Binding
use turso::{Connection, Result};
fn concurrent_write(db_url: &str) -> Result<()> {
let conn = Connection::open(db_url)?;
conn.execute("BEGIN CONCURRENT")?; // start MVCC transaction
conn.execute("INSERT INTO demo(id) VALUES (1)")?;
conn.execute("COMMIT")?; // commit – will abort if conflict
Ok(())
}
Python Binding
import turso
conn = turso.connect("<url>")
conn.execute("BEGIN CONCURRENT")
conn.execute("INSERT INTO demo VALUES (42)")
conn.commit() # Turso retries automatically on Busy errors
Key Implementation Files
The BEGIN CONCURRENT functionality spans several critical components:
parser/src/parser.rs– Parses the statement and assignsTransactionType::Concurrentcore/vdbe/execute.rs– VDBE opcode implementation callingbegin_mvcc_txand managing snapshot refresh (lines 55,500-55,560 and 56,430-56,560)core/mvcc/mod.rs– Documents MVCC guarantees and dirty write detection (lines 9-25)core/mvcc/database/*.rs– ContainsMvStoreandcommit_tx_no_connfor conflict detectiontests/integration/mvcc.rs– Integration tests validating concurrent writer behavior
Summary
- BEGIN CONCURRENT initiates MVCC transactions without acquiring exclusive write locks
- The parser tags transactions with
TransactionType::Concurrentinparser/src/parser.rs - Transactions pin consistent WAL snapshots via
begin_read_tx()andmvcc_refresh_if_db_changed() - Row versioning allows multiple writers to proceed simultaneously, with visibility checks in
core/mvcc/mod.rs - Write-write conflicts return
LimboError::Busyimmediately or trigger rollback at commit viacommit_tx_no_conn - Snapshot isolation guarantees consistent reads throughout the transaction lifetime
Frequently Asked Questions
What is the difference between BEGIN CONCURRENT and a regular transaction in Turso?
Regular transactions acquire exclusive write locks that block other writers until committed, while BEGIN CONCURRENT uses MVCC to allow multiple writers to proceed simultaneously. Regular transactions serialize access through locking, whereas concurrent transactions use optimistic concurrency control with conflict detection at commit time.
How does Turso detect write-write conflicts with BEGIN CONCURRENT?
Turso detects conflicts through the MVCC layer by checking row visibility—when a transaction attempts to write a row that has been modified by a concurrent transaction since the snapshot was taken, the system either returns LimboError::Busy immediately or validates the conflict during commit via the commit_tx_no_conn logic in core/mvcc/database.
What isolation level does BEGIN CONCURRENT provide?
BEGIN CONCURRENT provides snapshot isolation, ensuring that all reads within the transaction see a consistent database state as of the transaction start time. This prevents dirty reads and non-repeatable reads, even while other concurrent writers commit changes.
What happens when two concurrent transactions try to modify the same row?
Turso implements a first-writer-wins policy. The first transaction to commit successfully persists its changes. The second transaction encounters a conflict during commit validation and is rolled back, requiring the application to retry the transaction.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →