在MySQL数据库场景,使用mysqldump命令备份时,我们会遇到一个锁表的问题?如果进行锁表了,在备份期间用户就无法访问数,若是备份时长几个小时,那么就表示几个小时内,用户都无法访问数据,会对业务造成很大影响;如果不锁表,又会导致备份的数据不一致,因为在备份的过程中,有可能会有数据写入,这样无法保证备份后的备份文件中的数据是你想要的某个时间点的数据。

如何解决锁表问题?
关于MySQL备份时,是否需要锁表,这要根据公司的业务场景进行分析。
案例1:
某金融咨询公司,公司客户都是以select为主,即查询为主,公司的数据几乎全是公司内部导入,并且公司数据库引擎是混合引擎,MyIsam和Innodb两种存储引擎的表。
对于这种业务场景,可以不进行锁表,直接备份数据库即可,然后再通过binlog日志来保证数据的一致性(增量备份)
因为MySQL默认是开启--lock-tables参数的,若不需要锁表,则要关闭此参数--skip-lock-tables。
在用LOCK TABLES给表显式加表锁时,必须同时取得所有涉及到表的锁,也就是说,在执行LOCK TABLES后,只能访问显式加锁的这些表,不能访问未加锁的表;同时,如果加的是读锁,那么只能执行锁表的查询操作,MyISAM总是一次获得SQL语句所需要的全部锁。这也正是MyISAM表不会出现死锁(Deadlock Free)的原因。

#混合引擎和MyIsam引擎
mysqldump -uroot -p -A -B -F -R --skip-lock-tables --events|gzip >/tmp/all_$(date +%F).sql.gz

案例2:
在用户对数据更新频繁的业务场景中,使用mysqldump命令备份MySQL数据库,可使用锁表的功能了保证数据的一致性;但这样带来了一个问题,在备份锁表的期间,用户无法正常访问和更新数据。
对于这种场景,建议在业务低谷的时候进行备份,正所谓月黑风高杀人夜啊。
另一种更好的解决办法就是做主从复制,然后在从库上进行备份,这样子锁表产生的影响就会降得更低。
网上也有网友说使用--lock-tables只读锁表功能(即不能更新插入数据,只能读取数据锁表)来进行备份,然后通过binlog日志来达到数据一致性。这对于有可能有大量数据插入的场景,效果也不是很佳。
myisam引擎企业生产备份命令(适合所有引擎或混合引擎):
由于MyISAM引擎为表级锁,因此,在备份时需要防止在备份期间数据写入而导致不一致, 所以,在备份时使用--lock-all-tables(-x)锁表。

mysqldump -uroot -p -A -B -F -R -x -events|gzip >/tmp/all_$(date +%F).sql.gz

innodb引擎企业生产备份名:
InnoDB引擎为行锁,因此,备份时可以不对数据库加锁的操作,可以加选项--single-transaction进行备份。它有一些要求:只能是 innodb 引擎;导出的过程中,不能有任何人执行 alter table, drop table, rename table, truncate table等DDL语句。实际上DDL会被事务所阻塞,因为事务持有表的metadata lock 的共享锁,而DDL会申请metadata lock的互斥锁,所以阻塞了。

mysqldump -uroot -p -A -B -F -R --events --single-transaction|gzip >/tmp/all_$(date +%F).sql.gz

如有不当之处,请多多指教。

mysqldump参数详解:https://blog.51cto.com/13691477/2149675
MySQL锁知识:https://blog.csdn.net/mysteryhaohao/article/details/51669741