MySql的表锁行锁及间隙锁

上一篇 << 下一篇 >>>MySQL的并发文件及事务隔离级别


常用命令
手动新增表锁
lock table 表名称 read(write),表名称2 read(write);
查看表上加过的锁
show open tables;
删除表锁
unlock tables;

1.表锁

特点:
1.每次操作锁住整张表,开销小,加锁快;
2.不会出现死锁;
3.锁定粒度大,发生锁冲突的概率最高,并发度最低;

1.1 对表加读锁

例如:先执行lock table jarye_lock_myisam read;
在执行INSERT INTOjarye_lock_myisam (id, NAME) VALUES ('6', 'xiaomin');
报错:[Err] 1099 - Table 'jarye_lock_myisam' was locked with a READ lock and can't be updated
当前session和其他session都可以读该表
当前session中插入或者更新锁定的表都会报错,其他session插入或更新则会等待
select * from jarye_lock_myisam;

1.2 对表加写锁

例如:先执行lock table jarye_lock_myisam write;
当前session对该表的增删改查都没有问题,其他session对该表的所有操作被阻塞

1.3 总结

表锁中的读写锁区别:
读锁会阻塞写,不会阻塞读。
写锁则会把读写都阻塞。

表锁的加锁/解锁方式:(不需要用户干预,必须要显示的加LOCK TABLE命令)
MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁;
在执行更新操作 (UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁

2.行锁

特点:
1.每次操作锁住一行数据,开销大,加锁慢;
2.会出现死锁;
3.锁定粒度最小,发生锁冲突的概率最低,并发度最高。

行锁升级为表锁的情况
修改的时候查询的条件不是索引字段,则会走全表扫描。
全表扫描的时候对每行数据都加上行锁,最终形成表锁。其他任何行的操作都会被表锁,示例如下:

SessionA操作:
begin;
update jarye_account  set name='jarye6'  where balance='300';
commit;
在没commit的时候,会形成锁表,只能删除表锁unlock tables;

3.间隙锁

间隙锁是一个在索引记录之间的间隙上的锁。

sessionA操作:
begin;
update jarye_account  set name='jarye6' where id>18 and id<22;
commit;

从id>18 and id <22 上了间隙锁,在没有释放锁的时候 其他的session无法对该段位做操作。

sessionB
insert into `jarye_account` values (19, 'jarye19', '500');

主键索引或者唯一索引会使用间隙锁吗
1.如果where条件都命中的情况下,则不会发生间隙锁,只会增加记录锁
2.如果where条件部分命中或者全部没有命中的情况下,则使用间隙锁

4.优化注意事项

1.尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁
2.尽可能减少检索条件范围,避免间隙锁
3.尽量控制事务大小,减少锁定资源量和时间长度,涉及事务加锁的sql尽量放在事务最后执行

tips:项目中更多锁的情况请参考并发编程-锁的深入化、并发编程-锁的优化


推荐阅读:
<< << <<<查询和更新sql语句执行原理
<< << << << << << <<

你可能感兴趣的:(MySql的表锁行锁及间隙锁)