概述
锁是计算机中协调多个进程或线程并发访问某一资源的机制。
锁的分类
按数据操作类型分
分为读锁和写锁
1.读锁 共享锁-S锁-乐观锁
针对同一份数据,多个读操作可以同时进行而不会互相影响2.写锁 排他锁-X锁-悲观锁
当前写操作没有完成前它会阻断其他写锁和读锁
按数据操作粒度分
行锁和表锁和页锁
表锁
偏向MYISAM存储引擎,开销小,加锁快,无死锁,锁定粒度大,
发生锁冲突的概率最高,并发度最低。myisam级的读锁和写锁(偏读的引擎)表锁。
读锁
1 | # 手动增加读写锁 |
增加读锁以后
- 1.当前session无法进行update,insert等一系列其他操作
- 2.无法读除锁住表以外别的表的数据。
- 3.别的session可以读全部表的数据,不能修改锁表。
- 4.读阻塞写的。(其它session会一直等待)
- 5.别的session无法解除锁
写锁
1 | lock table mylock write; |
增加写锁之后
- 1.加了写锁以后,当前session只能对当前加了锁的表进行读写操作
- 2.其它session可以读其它的表,但不能读当前session锁住的。
MyISAM会在执行查询语句时(select)前,会自动给涉及的所有表加读锁,
在执行增删改操作前,会自动给涉及的表加写锁。简而言之就是,读锁会阻
塞写,但是不会阻塞读,而写锁则会把读和写都阻塞。
如何分析表锁定
1 | 1.show status like ‘table%’; |
行锁
偏向innodb存储引擎,开销大,加锁慢,会出现在死锁,锁定粒度最小,
发生锁冲突的概率最低,并发度也最高。innodb于myisam的最大不同有
两点:一是支持事务(transaction); 二是采用了行级锁。
行锁概念
- 1.建表
- 2.打开两个session
- 3.关闭两个session的自动提交
1
set autocommit = 0;
- 4.左边更新数据,右边更新同一个数据
- 5.select 查看对比,commit之后再对比。
当左边表更新时,右边更新同样的内容时阻塞,当阻塞过久会超时。右边更新不同行内容互不影响。 - 6.无索引或索引不当,引起的行锁升级成表锁
1
show index from test_innodb_lock;
- 7.如何锁定某一行这样锁定某一行后其它的操作会被阻塞,直到锁定某行的
1
2begin
select * from table where a=8 for update;
会话提交commit,重要的是加for update。
索引失效的影响
索引失效会效率下降,更恐怖的是行锁变表锁(当更新没有用到索引行时),
当读时,无索引会造成s锁,影响写入修改。
- 如:b本来是varchar类型,用了强制类型转换让索引失效这时候,session2无法同时更新别的数据,造成表锁。
1
update test_innodb_lock set a= 41 where b=4000;
InnoDB 行级锁是通过给索引上的索引项加锁来实现的,
InnoDB行级锁只有通过索引条件检索数据,才使用行级锁
否则,InnoDB使用表锁 在不通过索引(主 键)条件查询的、
时候,InnoDB是表锁而不是行锁。
行锁总结
1.做一套监控平台,自动发出调出来,当前你被锁了多少时间。
比如top命令里面的数据抓出来展现在平台上。2.innodb由于实现了行级锁定,虽然在锁定机制的实现方面所带
来的性能损耗可能比表级锁定会要更高一些,但是在整体并发处理
能力方面要远远优于myisam的表级锁定,当系统并发较高时,innodb
的整体性能和myisam相比就会有明显的优势了。3.但是innodb的行级锁定同样也有其脆弱的一面,当我们使用不当的时候,
可能会让innodb的整体性能表现不仅不能比myisam更高,甚至可能会更差。4.通过show status like ‘innodb_row_lock%’;来看行级锁的争夺。会显示:
1
2
3
4
5
6
71.innodb_row_lock_current_waits:当前正在等待锁定的数量
2.innodb_row_lock_time:从系统启动到现在锁定总时间长度
3.innodb_row_lock_time_avg:每次等待平均花的时间
4.innodb_row_lock_time_max
5.innodb_row_lock_waits:系统启动到现在总共等待的次数。
尤其当等待次数很高,而且每次等待时长也不小的时候,我们就需要分析系统中为什么会有如此多的等待,然后根据分析结果着手指定优化计划。
这个时候一定要用show profile分析,为什么会花费那么多等待时长。5.小建议优化
- 1.尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。
(varchar类型不加单引号是重罪) - 2.合理设计索引,尽量缩小锁的范围
- 3.尽可能较少的检索条件,避免间隙锁
- 4.尽量控制事务大小,减少锁定资源量和时间长度
- 5.尽可能低级别事务隔离
- 1.尽可能让所有数据检索都通过索引来完成,避免无索引行锁升级为表锁。
页锁
应用于BDB引擎,开销和加锁时间介于表锁和行锁之间,会出
现死锁,锁定粒度介于表锁和行锁之间,并发度一般。
间隙锁及其危害
当我们用范围条件而不是相等条件,innodb会给已有数据的索引项加锁,
对于值在范围内但不存在的记录,叫做间隙gap:innodb也会对这个间隙
加锁,这种机制就是所谓的间隙锁(next-key锁);(宁可错杀不可放过)
间隙锁
一般而言,为了做云计算和大数据分析,最好数据是连续的。
1 | session1 |