AD JB Toolbox 01 EN

MariaDB Tutorial / Compare Isolation Levels, Locks, and Deadlocks with Two Connections

Isolation controls which concurrent changes a transaction can read, while locks coordinate conflicting operations. Two separate connections with a controlled schedule can demonstrate REPEATABLE READ, READ COMMITTED, lock timeouts and deadlocks as distinct behaviors.

Prepare separate connections A and B

Open two command-line connections to the same learning server and shopcourse database. Check that CONNECTION_ID() differs, and run the setting-saving block below separately in each connection. Pasting both sides into one client does not create concurrency. Keep this lock experiment away from production data. Review transaction boundaries in Start InnoDB Transactions with COMMIT and ROLLBACK, and distinguish the SESSION values restored here from the configuration scopes in Inspect Server Settings, SQL Modes, Time Zones, and Logs.

SELECT CONNECTION_ID(),DATABASE(),@@SESSION.tx_isolation;
SET @saved_isolation=@@SESSION.tx_isolation;
SET @saved_wait=@@SESSION.innodb_lock_wait_timeout;

Create the table only in A, after checking the name and preserving any existing data:

USE shopcourse;
CREATE TABLE accounts_36_lab (
 account_id INT PRIMARY KEY,balance INT NOT NULL
) ENGINE=InnoDB;
INSERT INTO accounts_36_lab VALUES(1,1000),(2,2000);
Case Read or coordination rule Important distinction
Ordinary REPEATABLE READ SELECT A consistent-read snapshot within the transaction Different from current locking reads
Ordinary READ COMMITTED SELECT A committed version for each statement Repeated reads can change
Lock wait Wait for a conflicting lock to be released Timeout is not the same as deadlock

Check the MariaDB documentation for the syntax and conditions used here: for update, set transaction.

Compare REPEATABLE READ in A → B → A order

Start with account 1 at balance 1000 from the setup. Follow the connection labels; B runs only after A completes its first read.

A-1: establish the snapshot

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
START TRANSACTION;
SELECT balance FROM accounts_36_lab WHERE account_id=1;

B-1: commit a change

START TRANSACTION;
UPDATE accounts_36_lab SET balance=1100 WHERE account_id=1;
COMMIT;

A-2: read in the same transaction

SELECT balance FROM accounts_36_lab WHERE account_id=1;

A-1 and A-2 both return 1000. This compares consistent reads by ordinary SELECT, not the behavior of a locking/current read such as FOR UPDATE.

A-3: finish and read again

ROLLBACK;
SELECT balance FROM accounts_36_lab WHERE account_id=1;

The final read returns 1100. See SET TRANSACTION for the isolation-level scope.

Repeat READ COMMITTED from an explicit reset

B-0: reset the previous exercise

ROLLBACK;
START TRANSACTION;
UPDATE accounts_36_lab SET balance=1000 WHERE account_id=1;
COMMIT;

A-1: first READ COMMITTED read

ROLLBACK;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
START TRANSACTION;
SELECT balance FROM accounts_36_lab WHERE account_id=1;

B-1: commit 1100

START TRANSACTION;
UPDATE accounts_36_lab SET balance=1100 WHERE account_id=1;
COMMIT;

A-2: second read and finish

SELECT balance FROM accounts_36_lab WHERE account_id=1;
ROLLBACK;

A reads 1000 first and 1100 second because each ordinary read uses committed data visible to that statement. Choose an application isolation policy using write-conflict and business-consistency requirements as well.

Distinguish a held lock from a lock timeout

A-1: hold the lock on row 1

START TRANSACTION;
SELECT account_id,balance FROM accounts_36_lab
WHERE account_id=1 FOR UPDATE;

B-1: attempt the same row update

SET SESSION innodb_lock_wait_timeout=3;
START TRANSACTION;
UPDATE accounts_36_lab SET balance=balance+1 WHERE account_id=1;

With A still open, B should reach a lock timeout after about three seconds. Do not assume that this error cancels B’s entire transaction; explicitly finish both connections.

B-2: clean up the failed attempt

ROLLBACK;
SET SESSION innodb_lock_wait_timeout=@saved_wait;

A-2: release the lock

ROLLBACK;

FOR UPDATE transaction requirements

Create a deadlock with four interleaved steps

Ensure both previous transactions have ended. These are four interleaved steps, not one sequential script: switch windows in the order A-1 → B-1 → A-2 → B-2.

Step Connection Action
1 A row 1 UPDATE
2 B row 2 UPDATE
3 A row 2 UPDATE → wait
4 B row 1 UPDATE → deadlock detection

A-1: lock only the first row

START TRANSACTION;
UPDATE accounts_36_lab SET balance=balance+1 WHERE account_id=1;

B-1: lock the other row

START TRANSACTION;
UPDATE accounts_36_lab SET balance=balance+1 WHERE account_id=2;

A-2: request B’s row

UPDATE accounts_36_lab SET balance=balance+1 WHERE account_id=2;

A waits here. Switch to B and run the next statement without waiting for A to finish.

B-2: request A’s row

UPDATE accounts_36_lab SET balance=balance+1 WHERE account_id=1;

With InnoDB deadlock detection enabled, one transaction can receive Deadlock found; the victim is not fixed. Issue ROLLBACK; separately in both windows. An application needs bounded retries of the transaction with duplicate-operation protection.

Restore settings and use a consistent locking order

Acquire multiple rows in a consistent key order and keep transactions short to reduce deadlocks. Broad predicates and missing useful indexes can increase lock scope. Investigate the queries, logs and transaction sequence rather than classify a deadlock as a generic connection failure.

ROLLBACK;
SET SESSION tx_isolation=@saved_isolation;
SET SESSION innodb_lock_wait_timeout=@saved_wait;
SELECT @@SESSION.tx_isolation,@@SESSION.innodb_lock_wait_timeout;

Restore the saved settings independently in both connections. User variables disappear when a connection closes, so inspect new connections afresh. End both transactions before removing only the disposable test table.

DROP TABLE shopcourse.accounts_36_lab;
More in This Category
MariaDB Tutorial / Keep Unmatched Rows with LEFT JOIN

MariaDB Tutorial / Keep Unmatched Rows with LEFT JOIN

Retain all customers with LEFT JOIN, distinguish ON and WHERE filters, count actual right-side matches and compare no-order customers with customers lacking paid orders.

MariaDB Tutorial / Group Results with GROUP BY and Filter Groups with HAVING

MariaDB Tutorial / Group Results with GROUP BY and Filter Groups with HAVING

Create category-level COUNT and SUM reports, distinguish WHERE from HAVING, and reconcile expected groups. Review output grain, ONLY_FULL_GROUP_BY, NULL keys and joined duplicates.

MariaDB Tutorial / Build a Local MariaDB Lab with Docker Compose

MariaDB Tutorial / Build a Local MariaDB Lab with Docker Compose

Configure a local MariaDB container with Compose, file-based secrets, a healthcheck, and a named volume. Verify connections and distinguish container replacement from deleting persistent data.

MariaDB Tutorial / Break Queries into Named Steps with WITH and CTEs

MariaDB Tutorial / Break Queries into Named Steps with WITH and CTEs

Build a readable multi-step query with WITH, verify paid orders and per-order totals independently, and understand CTE scope, naming and execution-plan limitations.

MariaDB Tutorial / Change Table Structure Safely with ALTER TABLE

MariaDB Tutorial / Change Table Structure Safely with ALTER TABLE

Practice an add-fill-constrain migration with a product SKU column, verify counts and rejected duplicates, and review metadata locks, online-change limits and recovery boundaries.

MariaDB Tutorial / Summarize Rows with COUNT, SUM, AVG, MIN, and MAX

MariaDB Tutorial / Summarize Rows with COUNT, SUM, AVG, MIN, and MAX

Calculate and reconcile product counts, known-value counts, stock totals, averages and price bounds. Understand empty-input results and why the order of row calculations and aggregation matters.

MariaDB Tutorial / Create a Database with CREATE DATABASE, USE, and utf8mb4

MariaDB Tutorial / Create a Database with CREATE DATABASE, USE, and utf8mb4

Create a practice database with explicit utf8mb4 settings and verify its definition. Understand connection-local database selection, collation comparisons, and why IF NOT EXISTS preserves existing defaults.

MariaDB Tutorial / Read Related Rows with INNER JOIN

MariaDB Tutorial / Read Related Rows with INNER JOIN

Join customer names to orders with explicit relationship keys, interpret repeated customers correctly and compare filtered INNER JOIN results with an unrestricted Cartesian product.

MariaDB Tutorial / Import and Export CSV with Correct Paths, Types, and Encoding

MariaDB Tutorial / Import and Export CSV with Correct Paths, Types, and Encoding

Stage and validate a UTF-8 CSV before converting IDs and prices, then export through a server-side path. Review quoting, warnings, normalized duplicates, numeric bounds and field-level round-trip checks.

MariaDB Tutorial / Calculate Date Intervals, Differences, and Display Formats

MariaDB Tutorial / Calculate Date Intervals, Differences, and Display Formats

Compare calendar months, day differences and complete-hour differences with fixed MariaDB examples. Format dates correctly and select full months using explicit interval boundaries.