目录
锁是计算机协调多个线程并发执行的机制,事务并发处理时产生的问题,需要借助锁来解决
全局锁
全局锁对整个数据库加锁,这样整个数据库都陷入了“只读”状态,后序任何的更新操作都不能执行
典型的使用场景是对数据库的所有数据库的数据备份(对全部的数据库都会加锁)
增加全局锁:flush tables with read lock
mysql数据库提供了一个数据库备份的工具:mysqldump
mysqldump -uroot 数据库密码 备份数据库名称 > 备份数据库到哪一个sql文件
解锁 unlock tables
全局锁:
全局锁是对全库的锁,即使在一个数据库下建立全局锁,也是锁住了全部的数据库
数据备份:
会在指定位置创建文件
解除锁
全局锁的问题
1、如果在主库中备份数据,那么主库所有的更新操作都会阻塞
2、如果在从库中备份数据,那么从库备份期间,不能接受来自主库的二进制日志(binlog),导致主从延迟
(为了防止数据库出现异常,会设置主库和从库。数据库中有一个binlog文件,记录了数据库的所有SQL语句,以二进制文件的形式存储在磁盘当中,从库就是要复制这些SQL语句,将其在从库中执行一遍。如果在从库中备份数据,那么从库陷入只读操作,不能接收来自主库的二进制日志,导致有些SQL语句,从库没有执行,导致从库和主库的信息不对等)
表级锁
锁住某一张表,粒度(锁的作用范围)大,并发性最低,发生锁冲突的概率最高
表锁
加锁:lock tables 表名 read/write
解锁:unlock tables
表共享读锁
一旦某一个表增加了读锁,那么这个表无论是当前客户端还是其他客户端,都只能读,不能写
表独占写锁
一个客户端对一个表增加了写锁,那么这个客户端可以对这个表进行读和写操作,另外一个客户端对这个表的读和写都是阻塞的
元数据锁(MDL)
MDL是为了保护在并发状态下,元数据和表数据结构的一致性
如果有事务在进行增删改查的操作,保证其他事务不可以修改表结构
如果有事务正在修改表结构,那么不允许其他事务进行增删改查的操作
意向锁
意向锁分为意向共享锁和意向排他锁
意向共享锁:和表级的共享锁兼容,和表级排他锁互斥
意向排他锁:和表级的共享锁,表级排他锁互斥
意向锁之间相互兼容
行级锁(Innodb存储引擎支持)
每一次加锁锁住的是行数据,根据索引列加锁
行锁
两种类型的行锁
共享锁:一个事务获取了这行的共享锁,另外一个事务仍然可以获取这行数据的共享锁
排他锁:一个事务获取了这行的排他锁,另外一个事务不可以获取这行数据的共享锁和排他锁
间隙锁 临键锁
总结
锁模式 | 悲观锁 乐观锁 |
锁范围 | 全局锁 表锁 页锁 行锁 |
锁属性 | 共享锁 排他锁 |
锁状态 | 意向共享锁 意向排他锁 |
悲观锁:
数据库总是认为多个数据库并发操作会发生冲突,所以总是要求加锁操作。悲观锁主要体现为表锁、行锁、页锁。
乐观锁:
数据库认为多个数据库并发操作不会发生冲突,所以总是不加锁操作。所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。乐观锁的实现方式一般包括使用版本号和时间戳。
死锁
指两个或者两个以上的进程在执行过程中,因为争夺资源而造成的一种互相等待的现象
产生死锁的四个必要条件
1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放。
2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放。
3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放。
4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源。
如何避免死锁?
死锁的四个必要条件:互斥、占有且等待、不可强占用、循环等待。只要系统发生死锁,这些条件必然成立,但是只要破坏任意一个条件就死锁就不会成立。
在数据库层面,有两种策略通过「打破循环等待条件」来解除死锁状态:
- 设置事务等待锁的超时时间。当一个事务的等待时间超过该值后,就对这个事务进行回滚,于是锁就释放了,另一个事务就可以继续执行了。在 InnoDB 中
innodb_lock_wait_timeout
是用来设置超时时间的,默认值时 50 秒。当发生超时后,就出现下面这个提示:
- 开启主动死锁检测。主动死锁检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行。将参数
innodb_deadlock_detect
设置为 on,表示开启这个逻辑,默认就开启。当检测到死锁后,就会出现下面这个提示:
注意:
1、意向锁是InnoDB自动加的,不需用户干预。意向锁不会与行级的共享 / 排他锁互斥
2、排他锁指的是一个事务在一行数据加上排他锁后,其他事务不能再在其上加其他的锁。但可以直接通过select ...from...查询数据,因为普通查询没有任何锁机制
3、mysql InnoDb引擎中update,delete,insert语句自动加排他锁
4、
表级锁:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低
行级锁:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高
页面锁:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般