一、锁介绍
相对于其他的数据库而言,MySQL的锁机制比较简单,最显著的特点就是不同的存储引擎支持不同的锁机制。根据不同的存储引擎,MySQL中锁的特性可以大致归纳如下:
二、锁的分类
按数据操作的类型分类:
读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会互相影响。
写锁(排它锁):当前操作没有完成之前,它会阻断其他的写操作或读操作。
按数据操作的粒度分:
表锁:操作时,会锁定整个表。开销小,加锁快;不会出现死锁;锁定力度大,发生锁冲突概率高,并发度最低。
行锁:操作时,会锁定当前操作的表的某些行。开销大,加锁慢;会出现死锁;锁定粒度小,发生锁冲突的概率低,并发度高。
页锁:操作时,会锁定当前操作的表的某些页。开销和加锁速度介于表锁和行锁之间;会出现死锁;锁定粒度介于表锁和行锁之间,并发度一般。
三、MySQL的锁
MyISAM的表锁
MyISAM存储引擎在执行查询语句(SELECT),会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、DELETE、INSERT等),会自动给涉及的表加写锁,这个过程并不需要用户干预。
为了方便演示,我们利用系统提供的显式加锁指令:
-
读锁:lock table table_name read;
-
写锁:lock table table_name write;
-
解锁:unlock tables;
建立一个MyISAM存储引擎的表,并插入一些数据:
create table tb_myisam(
id INT AUTO_INCREMENT,
name VARCHAR(30),
age INT,
PRIMARY KEY(id)) engine=myisam;
insert into tb_myisam(name,age) value('zhang3',20);
insert into tb_myisam(name,age) value('li4',21);
insert into tb_myisam(name,age) value('wang5',22);
在两个会话终端来演示MyISAM的读锁:
演示MyISAM的写锁:
InnoDB的表锁和行锁
InnoDB存储引擎在执行更新操作(UPDATE、DELETE、INSERT等),会自动给涉及的表或行加写锁。
InnoDB存储引擎对于普通SELECT语句,不会加任何锁。如果读的数据正在执行UPDATE或DELETE操作,这时读操作不会等待写锁的释放,而是直接读取该数据的快照,具体读取那份快照数据,和系统的隔离级别有关。
对于SELECT语句,系统提供了显式加锁指令:
-
读锁:select * from table_name where ... lock in share mode;
-
写锁:select * from table_name where ... for update;
建立一个Innodb存储引擎的表,并插入一些数据:
create table tb_innodb (
id INT AUTO_INCREMENT,
name VARCHAR(30),
age INT,
PRIMARY KEY(id)) engine=innodb;
insert into tb_innodb(name,age) value('zhang3',20);
insert into tb_innodb(name,age) value('li4',21);
insert into tb_innodb(name,age) value('wang5',22);
为了方便演示,我们需要关闭系统的自动提交
演示InnoDB表的读锁:
演示InnoDB表的写锁:
演示InnoDB行的读锁:
演示InnoDB行的写锁: