InnoDB继承了标准的行级别的锁机制,提供了两种类型的锁。 *.共享锁(S) 允许一个事务获得只读一行的锁。 *.排他锁(X) 允许一个事务获得修改或者删除一行的锁。
假设一个事务T1在某一行上面获得一个s锁,那么事务T2可以获得对这一行的S锁,但是不能获得这 一行的X锁,需要等待。
假设一个事务T1在某一行上面获得一个x锁,那么事务T2既不能获得对这一行的S锁,也不能获得对这一行的X锁。都需要等待。
共享锁和排他锁的语句如下:
共享锁:SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE、
排他锁:SELECT * FROM table_name WHERE ... FOR UPDATE、
例子: MySQL数据准备:create database ztest;
use ztest;
create table zstudent(stu_id int not null AUTO_INCREMENT ,stu_name varchar(20),sex CHAR(1),PRIMARY KEY (`stu_id`)); 插入数据:
insert into zstudent(stu_name,sex) values('lzh','M');
insert into zstudent(stu_name,sex) values('zsd','M');
insert into zstudent(stu_name,sex) values('hk','M');
insert into zstudent(stu_name,sex) values('zc','M');
insert into zstudent(stu_name,sex) values('yf','M');
Innodb共享锁的例子
Session 1 set autocommit=0;
1)使用share mode 对stu_id=1的这一行加入共享锁(s).
(root@localhost) [ztest]> select * from zstudent where stu_id=1 lock in share mode;
+--------+-------------+------+
| stu_id | stu_name | sex |
+--------+-------------+------+
| 1 | zh | M |
+--------+-------------+------+
(4)事务1执行commit语句,释放共享锁
(root@localhost) [ztest]> commit;
Session 2
set autocommit=0;
2)事务2可以获得stu_id=1这一行的共享锁(S)。
(root@localhost) [ztest]> select * from zstudent where stu_id=1 lock in share mode;
+--------+-------------+------+
| stu_id | stu_name | sex |
+--------+-------------+------+
| 1 | zh | M |
+--------+-------------+------+
3)事务2却无法获得stu_id=1这一行的排他锁(X)。一直等待事务1的S锁释放。
(root@localhost) [ztest]> update zstudent set stu_name='zsd2' where stu_id=1;
…上述语句一直在等待,没有输出结果…
备注:
如果等待时间过长,会出现如下错误;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
(5)事务2获得排他锁,出现如下执行结果:
Query OK, 0 rows affected (2.99 sec)
Rows matched: 1 Changed: 0 Warnings: 0
最后执行commit,释放排他锁。