innodb行锁的陷阱(mysql行锁研究)
/我们有一张表:
create table mylock( id int(10) not null, name varchar(50), primary key(id) )engine=innodb default charset=utf8;
如果我问
update mylock set name='obama' where id=1;
会对那些数据加锁呢?
你一定会不加思索的说,在这个事务中,当然是id=1这一行,加上行锁嘛。
但是事实真是如此吗?那么让我们来做一个实验。
首先在你的mysql服务器上执行如下语句:
mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | ON | +---------------+-------+ 1 row in set (0.00 sec)
这表示你每一行语句都是自动提交的,在你执行完毕语句后,都是commit的。
我们需要执行以下语句,保证我们的几个session都是在一个事务之中。
mysql> set autocommit=0; Query OK, 0 rows affected (0.00 sec)
mysql> select * from mylock; +----+----------------+ | id | name | +----+----------------+ | 1 | Obama | | 2 | David Thompson | | 3 | 三毛 | | 4 | Mr.Homer | +----+----------------+ 4 rows in set (0.00 sec)
现在我们的表里有以上几条数据。
然后我们在第一个回话session1执行如下语句:
session1:
mysql> select * from mylock where name='Obama' for update; +----+-------+ | id | name | +----+-------+ | 1 | Obama | +----+-------+ 1 row in set (0.00 sec)
session2:
mysql> update mylock set name='Bush' where name ='Obama';
然后,session2就是长长的等待。
知道你去session1上commit之后,session2才更新成功。
mysql> update mylock set name='Bush' where name ='Obama'; Query OK, 1 row affected (14.51 sec) Rows matched: 1 Changed: 1 Warnings: 0
这个实验告诉我们,有些行锁是会锁住全表的。那么这些行是哪些行呢?
将在后面的实验进行解读。