上一篇 <<<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:项目中更多锁的情况请参考并发编程-锁的深入化、并发编程-锁的优化
网友评论