InnoDB行锁是经过给索引上的索引项加锁来实现的,这一点MySQL与ORACLE不一样,后者是经过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特色意味着:只有经过索引条件检索数据,InnoDB才使用行级锁,不然,InnoDB将使用表锁!mysql
在实际应用中,要特别注意InnoDB行锁的这一特性,否则的话,可能致使大量的锁冲突,从而影响并发性能。下面咱们经过一些实际例子,来加以说明。web
(1)在不经过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。sql
下面的例子中,开始tab_no_index表没有索引:session
mysql> create table tab_no_index(id int,name varchar(10)) engine=innodb;并发
Query OK, 0 rows affected (0.15 sec)性能
mysql> insert into tab_no_index values(1,'1'),(2,'2'),(3,'3'),(4,'4');spa
Query OK, 4 rows affected (0.00 sec)orm
Records: 4 Duplicates: 0 Warnings: 0索引
InnoDB存储引擎的表在不使用索引时使用表锁例子 ci
session_1 |
session_2 |
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> select * from tab_no_index where id = 1 ; +------+------+ | id | name | +------+------+ | 1 | 1 | +------+------+ 1 row in set (0.00 sec) |
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> select * from tab_no_index where id = 2 ; +------+------+ | id | name | +------+------+ | 2 | 2 | +------+------+ 1 row in set (0.00 sec) |
mysql> select * from tab_no_index where id = 1 for update; +------+------+ | id | name | +------+------+ | 1 | 1 | +------+------+ 1 row in set (0.00 sec) |
|
mysql> select * from tab_no_index where id = 2 for update; 等待 |
上面的例子中,看起来session_1只给一行加了排他锁,但session_2在请求其余行的排他锁时,却出现了锁等待!缘由就是在没有索引的状况下,InnoDB只能使用表锁。当咱们给其增长一个索引后,InnoDB就只锁定了符合条件的行,以下例所示:
建立tab_with_index表,id字段有普通索引
mysql> create table tab_with_index(id int,name varchar(10)) engine=innodb;
Query OK, 0 rows affected (0.15 sec)
mysql> alter table tab_with_index add index id(id);
Query OK, 4 rows affected (0.24 sec)
Records: 4 Duplicates: 0 Warnings: 0
InnoDB存储引擎的表在使用索引时使用行锁例子
session_1 |
session_2 |
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> select * from tab_with_index where id = 1 ; +------+------+ | id | name | +------+------+ | 1 | 1 | +------+------+ 1 row in set (0.00 sec) |
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec) mysql> select * from tab_with_index where id = 2 ; +------+------+ | id | name | +------+------+ | 2 | 2 | +------+------+ 1 row in set (0.00 sec) |
mysql> select * from tab_with_index where id = 1 for update; +------+------+ | id | name | +------+------+ | 1 | 1 | +------+------+ 1 row in set (0.00 sec) |
|
mysql> select * from tab_with_index where id = 2 for update; +------+------+ | id | name | +------+------+ | 2 | 2 | +------+------+ 1 row in set (0.00 sec) |