MySQL命令行操作限定单个数据库方法
写这篇文章的原因出自Kaijia一次被Stack Overflow坑的经历,回头看来虽然Stack Exchange的Peer Review机制很好,但是错误照样还是很多的,以及Kaijia提交了Edit被Peer Review拒绝了……
之前某个插件神不知鬼不觉地删除了所有WordPress数据表的主键和自增,导致系统出现异常,如果手动恢复的话要处理近30余张主键规则不同的表非常麻烦,于是Kaijia决定采用数据恢复的方式,即先将现有数据导出并删除表,再导入数据库备份重建表结构,再将现有数据导入。这样一来数据是现有的数据,表结构是损坏前的正确结构完成修复。
按照这个步骤下去,第二步是导入备份,但是Kaijia的数据库备份是全数据库整盘备份,单个SQL文件里面包含了所有数据库的数据,而本次恢复涉及单个数据库,不能影响其他数据库。之前没有类似经验无从下手,于是Kaijia搜索了下找到了此篇Stack Overflow问题《Can I restore a single table from a full mysql mysqldump file?》,高票回答是使用sed命令(完全正确),但是显然没有后面的正面回答(后来证实是坑)方便。后面回答的要旨非常简单:
1 |
mysql -u root -p 限定数据库 < dump.sql |
在mysql命令最后加上指定的数据库名便可以了!这不科学!但鉴于此答案有还有人点赞,还有人评论“This is what most people need.”于是Kaijia就尝试了……结果果真其他的数据库都被还原了,当然幸亏操作前Kaijia给服务器快照了一下,直接恢复了。
被坑完后,Kaijia认真研究了一下MySQL文档了解在mysql命令中加入指定数据库的意义,以及如何限定单个数据库操作。在MySQL的文档中,Kaijia找到了–one-database参数,文档的解释为:
–one-database, -o
Ignore statements except those that occur while the default database is the one named on the command line. This option is rudimentary and should be used with care. Statement filtering is based only on USE statements.
Initially, mysql executes statements in the input because specifying a database db_name on the command line is equivalent to inserting USE db_name at the beginning of the input. Then, for each USE statement encountered, mysql accepts or rejects following statements depending on whether the database named is the one on the command line. The content of the statements is immaterial.
翻译过来便是(Kaijia自己翻译的略显生疏):
忽略除了当选定的数据库和在命令行中指定的数据库相同时以外的所有语句。此参数为底层选项,应谨慎使用。语句过滤仅基于USE语句。
原先,MySQL执行所有输入的语句,因为在命令行中指定数据库db_name相当于在输入的最开始插入了一条USE db_name语句。现在(指增加了–one-database参数后),对于所有输入的USE语句,MySQL将基于数据库名称是否和命令行中的数据库名称相同决定是否接受或拒绝语句执行。语句内容在此是不重要的。
因此可以看出,在命令行中直接指明数据库名称实际上只是增加了一条SQL语句:
1 |
USE 此数据库; |
而数据库备份文件中肯定一开始就包含使用USE切换数据库的语句,所以上文的答案实际上和不指定数据库没有区别,其他数据库仍然会被影响到。正确限定单个数据库的方法便是增加–one-database参数,即:
1 |
mysql -u root -p --one-database 限定数据库 < dump.sql |
增加后,无论输入的语句如何切换数据库,都会被限定在指定的数据库中,在切换到其他数据库时的命令语句会自动被忽略的。
评论