MySQL (锁篇)

1、什么是锁?MySQL 中提供了几类锁?

锁是实现数据库并发控制的重要手段,可以保证数据库在多人同时操作时能够正常运行。

MySQL 提供了全局锁、行级锁、表级锁。其中 InnoDB 支持表级锁和行级锁,MyISAM 只支持表级锁。

 

2、什么是死锁?

死锁是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去。此时称系统处于死锁状态或系统产生了死锁。

 

3、如何处理死锁?

(1)通过 innodblockwait_timeout 来设置超时时间,一直等待直到超时;

(2)innodb_deadlock_detect = on 打开死锁检测,发现死锁之后,主动回滚死锁中的某一个事务,让其它事务继续执行。(默认选项)

 

4、如何查看死锁?

使用命令 show engine innodb status 查看最近的一次死锁。

InnoDB Lock Monitor 打开锁监控,每 15s 输出一次日志。使用完毕后建议关闭,否则会影响数据库性能。

 

5、如何开启死锁检测?

设置 innodbdeadlockdetect 设置为 on 可以主动检测死锁,在 Innodb 中这个值默认就是 on 开启的状态。

 

6、InnoDB 默认是如何对待死锁的?

InnoDB 默认是使用设置死锁时间来让死锁超时的策略,默认 innodblockwait_timeout 设置的时长是 50s。

 

7、什么是全局锁?它的应用场景有哪些?

全局锁就是对整个数据库实例加锁,它的典型使用场景就是做全库逻辑备份。 这个命令可以使整个库处于只读状态。使用该命令之后,数据更新语句、数据定义语句、更新类事务的提交语句等操作都会被阻塞。

 

8、如何设置数据库为全局只读锁?

使用命令 flush tables with read lock(简称 FTWRL)就可以实现设置数据库为全局只读锁。

 

9、使用全局锁会导致什么问题?

如果在主库备份,在备份期间不能更新,业务停摆,所以更新业务会处于等待状态。

如果在从库备份,在备份期间不能执行主库同步的 binlog,导致主从延迟。

 

10、什么是共享锁?

共享锁又称读锁 (read lock),是读取操作创建的锁。

其他用户可以并发读取数据,但任何事务都不能对数据进行修改,也就是说这时任何事务都不能获取数据上的排他锁,直到已释放所有共享锁。

但值得注意的是,事务T1对数据加了共享锁,事务T2同样可以在这条数据上添加共享锁。也就是说,一条数据上可以有多个共享锁同时存在。

 

11、什么是排它锁?

排他锁 (writer lock)又称写锁。

若某个事务对某一行加上了排他锁,那么只能这个事务对其进行写操作,在此事务结束之前,其他事务不能对其加任何锁。

其他事务可以读取数据,但不能进行写操作,需等待其释放。

排它锁是悲观锁的一种实现。

 

12、如何处理逻辑备份时,整个数据库不能插入的情况?

如果使用全局锁进行逻辑备份就会让整个库成为只读状态,幸好官方推出了一个逻辑备份工具 MySQLdump 来解决了这个问题。

只需要在使用 MySQLdump 时,使用参数 -single-transaction 就会在导入数据之前启动一个事务来保证数据的一致性,并且这个过程是支持数据更新操作的。

 

13、除了 FTWRL 可以设置数据库只读外,还有什么别的方法?

除了使用 FTWRL ( flush tables with read lock)外,还可以使用命令 set global readonly=true 设置数据库为只读。

 

14、FTWRL 和 set global readonly=true 有什么区别?

FTWRL 和 set global readonly=true 都是设置整个数据库为只读状态,但他们最大的区别就是,当执行 FTWRL 的客户端断开之后,整个数据库会取消只读,而 set global readonly=true 会一直让数据处于只读状态。

 

15、InnoDB 存储引擎有几种锁算法?

Record Lock — 单个行记录上的锁;

Gap Lock — 间隙锁,锁定一个范围,不包括记录本身;

Next-Key Lock — 锁定一个范围,包括记录本身。

 

16、InnoDB 如何实现行锁?

行级锁是 MySQL 中粒度最小的一种锁,他能大大减少数据库操作的冲突。

(1)共享锁:

SELECT … LOCK IN SHARE MODE,MySQL 会对查询结果集中每行都添加共享锁,前提是当前线程没有对该结果集中的任何行使用排他锁,否则申请会阻塞。

 
(2)排他锁:

SELECT ... FOR UPDATE,MySQL 会对查询结果集中每行都添加排他锁,在事物操作中,任何对记录的更新与删除操作会自动加上排他锁。前提是当前没有线程对该结果集中的任何行使用排他锁或共享锁,否则申请会阻塞。