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 / Connect Python to MariaDB and Use Parameterized Queries

MariaDB Tutorial / Connect Python to MariaDB and Use Parameterized Queries

Use a complete PyMySQL program to connect, insert, select, commit, and roll back. Keep apostrophes, Unicode, and injection-shaped inputs as values, and restrict dynamic sorting through an identifier allowlist.

MariaDB Tutorial / Join, Extract, Replace, and Measure Strings

MariaDB Tutorial / Join, Extract, Replace, and Measure Strings

Practice concatenation, substring extraction, replacement, trimming and string length in MariaDB. Compare NULL and empty inputs and distinguish Unicode characters from UTF-8 byte counts.

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 / Save Reusable Query Definitions with VIEW

MariaDB Tutorial / Save Reusable Query Definitions with VIEW

Create an INVOKER view for paid-order totals, inspect its definition and observe transaction changes. Review security, updateability, dependencies and the difference between a view and stored result data.

MariaDB Tutorial / Define a Table Structure with CREATE TABLE

MariaDB Tutorial / Define a Table Structure with CREATE TABLE

Define and inspect a MariaDB product-table schema using a complete CREATE TABLE example. Understand defaults, storage settings, IF NOT EXISTS, common errors, and a reset limited to the practice table.

MariaDB Tutorial / Schedule Database Tasks and Verify Event Results

MariaDB Tutorial / Schedule Database Tasks and Verify Event Results

Create a disabled one-time event, reschedule it into the future, and verify both execution metadata and its result row. Understand recurring-task overlap, retries, privileges, time zones, and cleanup.

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 / 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 / Compare Isolation Levels, Locks, and Deadlocks with Two Connections

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

Follow explicit A/B steps to compare isolation, row-lock waits and deadlocks. Complete blocks cover resetting values, rereading, cleaning up failures and restoring each connection’s settings.