数据库锁设计的初衷是处理并发问题,这也是数据库与文件系统的最大区别。html

根据加锁的范围,MySQL里大体能够分为三种锁:全局锁、表锁和行锁。接下来咱们会分三讲来介绍这三种锁,今天要讲的是全局锁。mysql

全局锁

全局锁,顾名思义,就是对整个数据库加锁。MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock(FTWRL)。sql

全局锁典型的应用场景是作全库的逻辑备份。数据库

经过FTWRL加全局锁

经过FTWRL确保不会有其余线程对数据库作更新,而后对整个库作备份。注意,在备份过程当中整个库彻底处于只读状态。并发

若是在主库上备份。那么在备份期间都不能执行更新。

若是在从库上备份。那么在备份期间,从库不能执行主库同步过来的 binlog,从而形成主从延时。

在备份过程当中数据库没法写,这对业务会有很大的影响,为何要加锁呢,不加锁行不行呢?工具

咱们来看看不加锁会怎样。以银行转帐为例。学习

mysql 备份 跳过某些表 mysql备份锁表吗_数据库

图1 备份同时在转帐

当用户A转100给用户B,若是在用户A帐户扣除了100,但还没给用户B帐户增长100时,对帐户表完成了备份,那此时备份数据与生产环境的数据出现不一致性。线程

也就是说,不加锁的话,备份获得的库不是一个逻辑时间点,这个视图是逻辑不一致的。当进行备份还原时,用户B帐户就少了100,这就出现很严重的问题了。设计

经过加全局锁会影响业务,那有更好的办法吗?

在事务隔离的实现原理那一篇文章里,咱们学习了事务隔离中的可重复读隔离级别是可以获得一致性视图的。而一致性视图可以确保数据的逻辑一致性。code

官方自带的逻辑备份工具是 mysqldump。当 mysqldump 使用参数 -single-transaction 的时候,导数据以前就会启动一个事务,来确保拿到一致性视图。而因为MVCC的支持,这个过程当中数据是能够正常更新的。查看这篇文章,了解更多关于MVCC和一致性读的内容。

有了一致性读后,还须要 FTWRL 吗?

一致性读是好,但前提是引擎要支持这个隔离级别。好比,对于MyISAM这种不支持事务的引擎,若是备份过程当中有更新,老是只能取到最新的数据,那么就破坏了备份的一致性。这时,咱们就须要使用FTWRL命令了。

因此 -single-transaction 方法只适用于全部的表使用事务引擎的库。

既然要全库只读,为何不使用set global readonly=true的方式呢?

虽然 readonly 也可以设置全库为只读状态。但仍是建议使用 FTWRL,缘由有两个:

在有些系统中,readonly的值会被用来作其余逻辑,好比用来判断一个库是主库仍是备库。所以,修改global变量的方式影响面更大,不建议你使用。

在异常处理机制上有差别。若是执行FTWRL命令以后因为客户端发生异常断开,那么MySQL会自动释放这个全局锁,整个库回到能够正常更新的状态。而将整个库设置为readonly以后,若是客户端发生异常,则数据库就会一直保持readonly状态,这样会致使整个库长时间处于不可写状态,风险较高。