Monday, 14 April 2014

MySQL InnoDB Row Level Locking Mechanism

We know that MySql InnoDB engine provides row level locking, while MyISAM can only do table level lock. But, InnoDB's row level locking mechanism may not be as what you expect. InnoDB doesn't really lock rows of data, instead, it set locks on every index record that is scanned in the processing of the SQL statement. This means, only when your SQL statement is using index to query data, InnoDB will use row level lock. Otherwise, InnoDB will use table level lock.

Let's do some simple tests.

create table called innodb_lock_test as below.  alter table innodb_lock_test add index id(id);

mysql> create table innodb_lock_test(id int,name varchar(10)) engine=innodb;
Query OK, 0 rows affected (0.15 sec)
mysql> insert into innodb_lock_test values(1,'Trimurthy'),(2,'Anand'),(3,'Krishna'),(4,'Prasad');
Query OK, 4 rows affected (0.00 sec)
Records: 4 Duplicates: 0 Warnings: 0


Now Lets open 2 sessions.

SESSION #1 :

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb_lock_test where id =1;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | Trimurthy |
+------+-----------+
1 row in set (0.00 sec)

SESSION #2 :

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb_lock_test where id =2;
+------+-------+
| id   | name  |
+------+-------+
|    2 | Anand |
+------+-------+
1 row in set (0.00 sec)


SESSION #1 :

mysql> select * from innodb_lock_test where id =1 for update;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | Trimurthy |
+------+-----------+
1 row in set (0.00 sec)


SESSION #2 :
mysql> select * from innodb_lock_test where id =2 for update;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

This example show us InnoDB can only use table level locking if no index is available. In session 1, it looks like we only set a lock on one row (where id=1 for update). But we don't have index on id column, InnoDB is actually locking the whole table, so in session two, when we try to set a lock to a different row(where id=2 for update), we have to wait until the lock in session 1 is released.

Now, let's add index to our id column and repeat the same test.

mysql> alter table innodb_lock_test add index id(id);
Query OK, 0 rows affected (0.24 sec)
Records: 0  Duplicates: 0  Warnings: 0

SESSION #1 :

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb_lock_test where id =1;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | Trimurthy |
+------+-----------+
1 row in set (0.00 sec)

SESSION #2 :

mysql> set autocommit=0;
Query OK, 0 rows affected (0.00 sec)

mysql> select * from innodb_lock_test where id =2;
+------+-------+
| id   | name  |
+------+-------+
|    2 | Anand |
+------+-------+
1 row in set (0.00 sec)


SESSION #1 :

mysql> select * from innodb_lock_test where id =1 for update;
+------+-----------+
| id   | name      |
+------+-----------+
|    1 | Trimurthy |
+------+-----------+
1 row in set (0.00 sec)


SESSION #2 :

mysql> select * from innodb_lock_test where id =2 for update;
+------+-------+
| id   | name  |
+------+-------+
|    2 | Anand |
+------+-------+
1 row in set (0.00 sec)

If we observer session1 and session2 both the queries got executed(means both the queries got locks on respective rows) because of index.

CONCLUSION : InnoDB row level locks works only when your SQL statement is using index to query data.


MySQL InternalsMySQL HighAvailabilityMySQL Performance TuningMySQL Query OptimizationMySQL performanceMySQL FabricMySQL HAMySQL InstallationMySQL UpgradeInnoDB Performance TuningInnoDB Buffer Pool SizeMySQL Performance TuningMySQL ClusterMySQL Latest NewsNews and EventsMySQL Customers

No comments:

Post a Comment