Transaction control, isolation levels, and concurrency management in CockroachDB
Transactions ensure that a group of SQL statements execute atomically - either all succeed or all fail together. CockroachDB provides ACID-compliant transactions with multiple isolation levels.
CockroachDB supports three SQL isolation levels that map to internal isolation implementations.
SERIALIZABLE
REPEATABLE READ
READ COMMITTED
BEGIN ISOLATION LEVEL SERIALIZABLE;-- Strongest isolation-- Transactions appear to execute serially-- May retry on conflictsUPDATE inventory SET quantity = quantity - 1WHERE product_id = 5 AND quantity > 0;INSERT INTO orders (product_id, quantity) VALUES (5, 1);COMMIT;
Characteristics:
Strongest consistency guarantees
Prevents all anomalies (dirty reads, non-repeatable reads, phantoms)
Default isolation level
May experience transaction retries under contention
BEGIN ISOLATION LEVEL REPEATABLE READ;-- Also called SNAPSHOT isolation-- Reads see consistent snapshotSELECT COUNT(*) FROM orders WHERE status = 'pending';-- Will see same count if queried again in this transactionCOMMIT;
Characteristics:
Reads operate on a consistent snapshot
Prevents dirty reads and non-repeatable reads
Better performance than SERIALIZABLE
Mapped to Snapshot isolation internally
BEGIN ISOLATION LEVEL READ COMMITTED;-- Each statement sees latest committed data-- Different statements may see different snapshotsSELECT balance FROM accounts WHERE id = 1;-- Another transaction commits hereSELECT balance FROM accounts WHERE id = 1;-- May see different valueCOMMIT;
Priority affects which transactions win during conflicts.
Priority Levels
Use Cases
Setting Priority
-- HIGH priority (wins conflicts with NORMAL/LOW)BEGIN PRIORITY HIGH;UPDATE critical_data SET value = value + 1;COMMIT;-- NORMAL priority (default)BEGIN PRIORITY NORMAL;UPDATE data SET value = value + 1;COMMIT;-- LOW priority (yields to NORMAL/HIGH)BEGIN PRIORITY LOW;SELECT * FROM logs;COMMIT;
HIGH priority:
Critical business transactions
Time-sensitive operations
Operations that must not be retried
NORMAL priority:
Standard application transactions
Default for most use cases
LOW priority:
Background jobs
Analytics queries
Batch processing that can be retried
-- At transaction startBEGIN PRIORITY HIGH;-- During transaction (before any statements)BEGIN;SET TRANSACTION PRIORITY HIGH;UPDATE accounts SET balance = balance + 100;COMMIT;-- Session defaultSET default_transaction_priority = 'high';
BEGIN;SAVEPOINT cockroach_restart;-- Your transaction logicUPDATE inventory SET quantity = quantity - 1 WHERE product_id = 5;-- Check for retryRELEASE SAVEPOINT cockroach_restart;COMMIT;-- On retry error (40001), rollback to savepoint and retry
-- Show current transaction statusSHOW TRANSACTION STATUS;-- Show transaction isolation levelSHOW TRANSACTION ISOLATION LEVEL;-- Show transaction prioritySHOW TRANSACTION PRIORITY;-- Check if in transactionSELECT current_setting('transaction_isolation');
BEGIN;-- Timestamp at transaction startSELECT TRANSACTION_TIMESTAMP();-- Same value throughout transactionSELECT TRANSACTION_TIMESTAMP();-- Statement timestamp (changes per statement)SELECT STATEMENT_TIMESTAMP();COMMIT;
Query data as it existed at a specific point in time.
Timestamp Query
Transaction Time Travel
Follower Reads
-- Read data from 1 hour agoSELECT * FROM users AS OF SYSTEM TIME '-1h';-- Specific timestampSELECT * FROM orders AS OF SYSTEM TIME '2026-03-03 10:00:00';-- Interval syntaxSELECT * FROM products AS OF SYSTEM TIME INTERVAL '-30m';
BEGIN AS OF SYSTEM TIME '-1h';-- All queries in this transaction see data from 1 hour agoSELECT COUNT(*) FROM orders;SELECT * FROM order_items WHERE order_id = 100;COMMIT;
-- Read from closest replica (reduced latency)SELECT * FROM users AS OF SYSTEM TIME follower_read_timestamp();-- Slightly stale but much faster-- Useful for read-heavy workloads
Historical reads are subject to the garbage collection window (default 25 hours). Data older than this window may not be available.
BEGIN;-- Set for current transaction onlySET TRANSACTION ISOLATION LEVEL SERIALIZABLE;SET TRANSACTION PRIORITY HIGH;SET TRANSACTION READ ONLY;-- Your queries hereCOMMIT;
-- Transaction in a specific regionBEGIN;-- Queries automatically route to appropriate regionsUPDATE users SET last_login = now() WHERE id = 1;INSERT INTO login_log (user_id, timestamp) VALUES (1, now());COMMIT;
BEGIN;-- Verify balanceSELECT balance FROM accounts WHERE id = 1 FOR UPDATE;-- Transfer moneyUPDATE accounts SET balance = balance - 100 WHERE id = 1;UPDATE accounts SET balance = balance + 100 WHERE id = 2;-- Record transactionINSERT INTO transfers (from_account, to_account, amount) VALUES (1, 2, 100);COMMIT;
BEGIN ISOLATION LEVEL SERIALIZABLE;-- Check and decrement inventoryUPDATE inventory SET quantity = quantity - 1WHERE product_id = 5 AND quantity > 0RETURNING quantity;-- Create order if inventory was availableINSERT INTO orders (product_id, quantity) VALUES (5, 1);COMMIT;
BEGIN;-- Make changeUPDATE users SET status = 'inactive' WHERE id = 1RETURNING id, status;-- Record audit entryINSERT INTO audit_log (table_name, record_id, action, changed_at)VALUES ('users', 1, 'status_change', CURRENT_TIMESTAMP);COMMIT;
-- Active transactionsSELECT * FROM crdb_internal.cluster_transactions;-- Transaction statisticsSELECT * FROM crdb_internal.node_transaction_statisticsORDER BY count DESCLIMIT 10;