Databases 4 min read

Understanding MySQL SELECT ... FOR UPDATE Locking: Row vs. Table Locks

This article explains how MySQL's SELECT ... FOR UPDATE statement acquires either row-level or table-level locks depending on the presence of indexes or primary keys, and demonstrates the behavior with multiple transaction examples and a sample table definition.

Architect's Tech Stack
Architect's Tech Stack
Architect's Tech Stack
Understanding MySQL SELECT ... FOR UPDATE Locking: Row vs. Table Locks

Hello everyone, I am Peng Lei.

A plain SELECT statement does not lock rows, but SELECT ... FOR UPDATE not only queries data but also acquires a pessimistic lock.

Whether the lock is a row lock or a table lock depends on whether the query uses an indexed column or a primary key. Without an index or primary key, the statement locks the entire table; otherwise it locks only the matching rows.

Verification:

Table creation SQL:

// id is the primary key
// name is a unique index
CREATE TABLE user (
  id INT(11) NOT NULL AUTO_INCREMENT,
  name VARCHAR(255) DEFAULT NULL,
  age INT(11) DEFAULT NULL,
  code VARCHAR(255) DEFAULT NULL,
  PRIMARY KEY (id),
  KEY idx_age (age) USING BTREE
) ENGINE=INNODB AUTO_INCREMENT=1570068 DEFAULT CHARSET=utf8;

Auto‑commit must be disabled for the test: SET @@autocommit=0; (0 = manual commit, 1 = automatic).

Combined Example Verification

Example 1

Query using the primary‑key id in one transaction, then start another transaction that attempts to update the same row. The update is blocked because the first transaction holds a row lock on the row with id=1 .

Figure 1 shows the first transaction (not yet committed). Figure 2 shows the second transaction attempting the update and being blocked. Figure 3 shows the second transaction eventually timing out.

Example 2

Start a transaction that updates a different row (id=2). The update proceeds without blocking because the first transaction locked only the row with id=1.

Example 3 (Index)

The table was created with a unique index on the age column.

Example 4

Use a non‑indexed column code in the SELECT ... FOR UPDATE query.

Another transaction updates a different row. If the update succeeds, a row lock was taken; if it fails, the statement locked the whole table.

Result

If the query condition uses an indexed column or primary key, SELECT ... FOR UPDATE acquires a row lock.

If the condition uses a non‑indexed column, the statement locks the entire table.

MySQLIndexesdatabase transactionsRow Locktable lockSELECT FOR UPDATE
Architect's Tech Stack
Written by

Architect's Tech Stack

Java backend, microservices, distributed systems, containerized programming, and more.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.