HOME/Articles/

MySQL锁

Article Outline

MySQL锁

1、锁的分类:

表锁:

在操作时,会锁定整个表;表锁一般用于MYISAM引擎,表锁的特点是:开销小,加锁快,不会出现死锁;锁的粒度大,发生锁冲突的概率最大(因为每次都是锁住整张表,如果另一个事务也查询该表的话,就会出现锁冲突),并发度最低。

行锁:

操作时,会锁定当前操作行;行锁一般用于InnoDB存储引擎,开销大,加锁慢,或出现死锁,锁的粒度最小,发生锁冲突的概率最低,并发度高,读锁会阻塞写,但是不会阻塞读;写锁既会阻塞读,又会阻塞写;

在无索引时,因为无法确定查询确定的返回,InnoDB会对整表加锁,实际效果跟表锁一样。

间隙锁:

当使用范围条件查询,而不是使用相等条件检索数据,并请求共享(读锁)或排他锁(写锁)时,InnoDb会给符合条件的已有数据进行加锁,在范围内但是并不存在的记录,叫做间隙,InnoDB也会对这个间隙加锁,这种锁机制,就是所谓的间隙锁。这种间隙锁会影响到数据的查询;

2、InnoDB锁的建议

  • 当更新数据或者插入数据时,尽量限制好范围,减少间隙锁的影响
  • 尽可能让所有的数据检索都能通过索引完成,避免无索引导致行锁升级为表锁。
  • 合理设计索引,尽量缩小锁的范围;
  • 尽可能减少查询条件以及查询范围,避免间隙锁;
  • 尽量控制事务大小,减少锁定资源量和时间长度
  • 尽可能使用低级别的事务隔离机制;

3、实例

id name sex
1 张三 0
10 李四 1

1、首先,构建一张这样的表,叫做student;

2、关闭自动提交机制 set autocommit =0;

3、新开启一个查询事务

begin;
select * from t where id between 0 and 10 for update;

暂时不进行commit;提交

4、此时,1到10之间,虽然不存在其他id,但是由于间隙锁,会将表锁住;

5、开启一个新的事务,尝试插入一条 id为4的数据,如下

insert into  Student (id, name, sex) values (4,'aaaa',1);

会发现直到步骤3提交之前,步骤5的插入操作一直处于阻塞状态。