1.锁的概念
锁是计算机协调多个进程或线程并发访问同一资源的机制。数据库系统使用锁是为了支持对共享资源进行并发访问访问,提供数据的完整性和一致性
2.锁的作用
在数据库中,除传统的资源(内存,cpu等)的争用外,数据也是一种供许多用户使用的数据,如何保证数据的一致性和有效性是所有数据库必须解决的一个问题,锁冲突也是影响数据库并发访问的一个重要因素,锁就解决上面这些问题
3.锁的分类
按操作类型分为:
读锁(共享锁): 针对同一份数据,多个读操作可以同时进行而不会影响
写锁(排它锁): 针对同一份数据,多个写操作不可以同时进行,会发生进程堵塞情况
按操作力度分为:
页面锁: 对整个页面上锁
表锁: 对整个表上锁,当表锁时,其他进程想读该表,必须等待锁的释放,程堵塞状态
行锁: 对某条数据上锁,当该行锁住时,其它进程无法访问操作该条数据,但不影响其它进程访问别的数据
4.表锁
4.1 表级锁的两种概念
1.表共享锁2.表独占锁
区别:读锁会阻塞写,但不会阻塞读;但写锁会阻塞读和写
4.2 特点
1.偏向在MyISAM存储引擎,开销小,加锁快2.无死锁
3.锁力度大,发生冲突的概率高,并发度最低
4.3 引发表锁条件
1.手动加锁2.操作数据库时
4.4 分析
命令:show status like ‘table%’
返回结果:
结果分析:
Table_locks_immediate:产生表锁定的次数,即表示立即获取锁的查询次数,每立即获取锁1次该值加1
Table_locks_waited:出现表级锁定争用而发生等待的次数,即不能立即获取锁的次数,每等待1次该值加1,此值高则说明存在较严重的表级锁争用情况
MyISAM 的读写锁调度是写有先,写锁后,其他线程不能做任何操作,大量的更新会时查询很难得到锁,从而造成用于的阻塞,所以MyISAM不适合做写为主的引擎
5.行锁
5.1 特点
1.偏向InnoDB存储引擎,开销大,加锁慢(存在Next-Key锁);2.会出现死锁;
3.锁定力度最小,发生锁冲突的概率最低,并发度也最高
5.2 引发表锁条件
1.手动加锁2.操作数据库时
5.3 行锁升级为表锁的条件
1.无索引行锁升级为表锁
举例:比如更新id为1的这条数据,如果id有索引,就会上把该对应的索引上锁,但是id没有索引,这时候就是表锁。这也想到我们公司建表的规定,id必须建索引,可能一方面也是出于这样的考虑( InnoDB的行锁是针对索引加的锁,不是针对记录加的锁。并且该索引不能失效,否则都会从行锁升级为表锁)2.大量 更新或全表更新,行锁会升级为表锁
MySQL 认为大量对一张表使用行锁,会导致事务执行效率低,从而可能造成其他事务长时间锁等待和更多的锁冲突问题,性能严重下降。所以MySQL会将行锁升级为表锁,即实际上并没有使用索引5.4 间隙锁
我们用范围条件而不是相等条件检索时,并请求共享或排它锁时,InnoDB会给符合条件的已有数据记录的索引项加锁, 对符合条件的但并不存在的记录,叫“间隙”。InnoDB会对这个“间隙”加锁,这种机制即为“间隙锁” 。(比如查询id 在1到10的范围是,会对id在1到10的记录都加锁,但是数据库不存在id=2这条记录,这时想插入一条id=2的记录/是无法插入的,因为id=2这条数据已被加上了间隙锁)5.5 分析
命令:show status like ‘innodb_row_lock%’
返回结果:
结果分析:
Innodb_row_lock_current_waits:当前正在等待锁的数量;
Innodb_row_lock_time:从系统启动到现在锁定总时间长度;
Innodb_row_lock_time_avg:每次等待所花平均时间;
Innodb_row_lock_time_max:从系统启动到现在等待最长的一次所花的时间长度;
Innodb_row_lock_waits:系统启动到现在总共等待的次数;
当等待次数很高,而且每次等待时长也很大的时候,我们就要分析系统中为什么有这么多的等待,然后根据分析结果来制定优化
5.5 优化
1.让所有的数据通过索引来检索2.合理设计索引,尽量缩小锁的范围
3.尽可能减少锁的条件,避免间隙锁
4.控制事务大小,减少锁定资源量和时间的长度
5.降低事务隔离级别
6.锁冲突
锁冲突:是等待别人释放我需要的锁资源,即当操作这个资源时,此资源已上锁,我就需要等待释放次锁
7.死锁
7.1 what
死锁:互相等待对方持有的锁7.2 死锁举例
7.3 死锁的原因
7.4 发生死锁的必要条件
锁冲突和死锁不是一个概念,有本质区别,锁冲突会按顺序执行,死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象, 若无外力作用,它们都将无法推进下去。
事务的属性及级别