InnoDB行锁是通过给索引上的索引项加锁来实现的,这一点MySQL与ORACLE不同,后者是通过在数据块中对相应数据行加锁来实现的。InnoDB这种行锁实现特点意味着:只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁!

在实际应用中,要特别注意InnoDB行锁的这一特性,不然的话,可能导致大量的锁冲突,从而影响并发性能。下面我们通过一些实际例子,来加以说明。

(1)在不通过索引条件查询的时候,InnoDB确实使用的是表锁,而不是行锁。

下面的例子中,开始tab_no_index表没有索引:

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'); 


Query OK, 4 rows affected (0.00 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_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) 

原文请点:http://blog.chinaunix.net/u2/69385/showart_1852286.html