MySQL Lock and unlock tables Tutorial and Examples
In this article, you will learn how to acquire and release table locks using MySQL LOCK TABLES and UNLOCK TABLES statements.
Suppose there is such logic in a banking system:
- When user A withdraws 500 yuan from his bank account, user A’s balance is the original balance minus 500.
- When another user B transfers 500 yuan to the user A, the balance of user A is the original balance plus 500.
If these two operations occur at the same time, the balance of the User A may be wrong.
MySQL locks are designed to solve this concurrency problem. MySQL supports three types of locks: table-level locks, row-level locks, and page locks.
MySQL allows you to acquire table locks explicitly within a session to prevent other sessions from modifying the table during periods when you need exclusive access to the table.
Table locks is performed in the current session. A session can only acquire locks for itself, and can only release its own locks.
MySQL provides LOCK TABLES and UNLOCK TABLES statements for explicitly acquiring and releasing table locks.
MySQL table lock syntax
MySQL LOCK TABLES syntax
To acquire table locks explicitly for the current session, use the LOCK TABLES statement as following:
LOCK TABLES
table_name [READ | WRITE]
[, table_name [READ | WRITE], ...];
Here:
- The
table_nameis the table name on which you want to acquire the lock. READandWRITEare lock types.READLocks are used for shared read tables, andWRITElocks are used for exclusive read-write tables.- You can acquire locks on multiple tables in one statement. Use commas to separate multiple table locks.
- The
LOCK TABLESstatement implicitly releases all table locks held by the current session before acquiring a new table lock. - You can use
LOCK TABLEinstead ofLOCK TABLES.
MySQL UNLOCK TABLES syntax
To release all table locks acquired by the current session, use the following statement:
UNLOCK TABLES;
Lock Types
Table locks support two types of locks: READ and WRITE. READ Locks are used for shared read tables, and WRITE locks are used for exclusive read-write tables. Their characteristics are as follows。
READ Lock
-
A session holding a table lock can only read the table, but not write to it.
-
Multiple sessions can acquire
READlocks. -
Other sessions can read the table without explicitly acquiring the
READlock, but cannot write to the table. Writes from other sessions will wait until the read lock is released.
WRITE Lock
-
The session holding the lock can read and write the table.
-
Only the session holding the lock can access the table. Other sessions cannot access it until the lock is released.
-
Lock requests to the table by other sessions will be blocked while the
WRITElock is held.
If you do not explicitly release the table lock, when the session ends, both the READ lock and the WRITE lock will be released by MySQL.
MySQL Table Locks Examples
This example demonstrates how to acquire table locks (READ and WRITE locks) and release table locks in MySQL.
We use the following testdb statement to create a table named test_lock in the database to practice our example:
CREATE TABLE `test_lock` (
`id` int NOT NULL AUTO_INCREMENT,
`txt` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
);
If you do not have a testdb database, create a database and select the database using the following statement first:
CREATE DATABASE testdb;
use testdb;
READ Lock Examples
The READ lock is a shared read lock. Let us understand the characteristics of READ locks.
-
First, open a session and use the
SHOW PROCESSLISTstatement view the ID of the current session:SHOW PROCESSLIST;+----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 201156 | Waiting on empty queue | NULL | | 8 | root | localhost | testdb | Query | 0 | init | show PROCESSLIST | +----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+Here, the ID of the current session is 8.
-
Insert a new row into the table without acquiring the
READlock,INSERT INTO test_lock(txt) VALUES('Hello');It can be inserted normally here.
-
Use the following
LOCK TABLESstatement to acquire aREADlock on thetest_locktable:LOCK TABLES test_lock READ; -
Let’s insert a new row into the table with the
READlock,INSERT INTO test_lock(txt) VALUES('Hello World');At this point, MySQL gives an error: “ERROR 1099 (HY000): Table ’test_lock’ was locked with a READ lock and can’t be updated”.
-
You can reopen a session and test the
READlock in a new session:SELECT * FROM test_lock;+----+-------------+ | id | txt | +----+-------------+ | 1 | Hello | +----+-------------+This means that the other sessions can also read the table.
-
Test WRITE operation in a new session. Please execute the above
INSERTstatement in the session. You will find that the operation will be suspended until the read lock on the table is released. -
You can use the
SHOW PROCESSLISTstatement see if the session is pending:SHOW PROCESSLIST;+----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 201156 | Waiting on empty queue | NULL | | 8 | root | localhost | testdb | Query | 0 | init | show PROCESSLIST | | 9 | root | localhost | testdb | Query | 16 | Waiting for table metadata lock | INSERT INTO test_lock(txt) VALUES('Hello World') | +----+-----------------+-----------+--------+---------+--------+---------------------------------+--------------------------------------------------+You can see that the session with Id 9 is waiting for the lock to be released and its status is:
Waiting for table metadata lock.
WRITE Lock Examples
The WRITE lock is an exclusive lock. Only the session holding the lock can access the table, and operations on the table by other sessions will wait for the lock to be released. Let us understand the characteristics of WRITE locks.
-
First, open a session and acquire the
WRITElock on thetest_locktable.LOCK TABLES test_lock WRITE; -
Insert a new row into the
test_locktable.INSERT INTO test_lock(txt) VALUES('Hi');Insertion succeeded. This means that the session holding the write lock on the table can write to the table.
-
Query data from the
test_locktable:SELECT * FROM test_lock;+----+-------------+ | id | txt | +----+-------------+ | 1 | Hello | | 2 | Hello World | | 3 | Hi | +----+-------------+Search successful. This means that the session holding the write lock on the table can read the table.
-
Start another session and try to read the data:
SELECT * FROM test_lock;You will notice that the operation is in a state of waiting and has not returned.
-
You can use the
SHOW PROCESSLISTstatement view the status of the sessionSHOW PROCESSLIST;+----+-----------------+-----------+--------+---------+--------+---------------------------------+-------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+-----------------+-----------+--------+---------+--------+---------------------------------+-------------------------+ | 5 | event_scheduler | localhost | NULL | Daemon | 202266 | Waiting on empty queue | NULL | | 8 | root | localhost | testdb | Query | 0 | init | SHOW PROCESSLIST | | 9 | root | localhost | testdb | Query | 81 | Waiting for table metadata lock | SELECT * FROM test_lock | +----+-----------------+-----------+--------+---------+--------+---------------------------------+-------------------------+ -
Release the held lock in the first session using the following statement:
UNLOCK TABLES;You will see the result of the execution of the
SELECTstatement as follows:+----+-------------+ | id | txt | +----+-------------+ | 1 | Hello | | 2 | Hello World | | 3 | Hi | +----+-------------+
Conclusion
MySQL allows you to explicitly acquire table locks within a session using the LOCK TABLES statement to prevent other sessions from modifying the table during periods when you need exclusive access to the table.
MySQL allows you to explicitly release table locks within a session using the UNLOCK TABLES statement.
There are two types of MySQL table locks: shared read locks and exclusive read-write locks.