提问人:DanielAttard 提问时间:5/24/2013 最后编辑:Jesse NicklesDanielAttard 更新时间:10/22/2023 访问量:84893
导入数据库时如何忽略某些MySQL表?
How to ignore certain MySQL tables when importing a database?
问:
我有一个大型 SQL 文件,其中包含一个数据库和大约 150 个表。我想用于导入该数据库,但是,我希望导入过程忽略或跳过几个表。导入所有表但忽略其中一些表的正确语法是什么?谢谢。mysqlimport
答:
mysqlimport
不是导入 SQL 语句的正确工具。此工具旨在导入格式化的文本文件,例如 CSV。您要做的是使用 如下 命令将 sql 转储直接馈送到客户端:mysql
bash > mysql -D your_database < your_sql_dump.sql
既不提供也不提供您需要的功能。最好的机会是导入整个转储,然后删除不需要的表。mysql
mysqlimport
如果您有权访问转储来自的服务器,则可以使用 创建一个新的转储。mysqldump --ignore-table=database.table_you_dont_want1 --ignore-table=database.table_you_dont_want2 ...
评论
如果需要,您可以一次执行一个表:
mysqldump -p sourceDatabase tableName > tableName.sql
mysql -p -D targetDatabase < tableName.sql
RandomSeed 接受的答案可能需要很长时间!导入表(稍后删除它)可能会非常浪费,具体取决于大小。
对于使用
mysqldump -u user -ppasswd --opt --routines DBname > DBdump.sql
我目前得到一个大约 7GB 的文件,其中 6GB 是我“不需要”在那里的日志表的数据;重新加载此文件需要几个小时。如果我需要重新加载(出于开发目的,或者如果需要实时恢复),我会这样浏览文件:
sed '/INSERT INTO `TABLE_TO_SKIP`/d' DBdump.sql > reduced.sql
并重新加载:
mysql -u user -ppasswd DBname < reduced.sql
这给了我一个完整的数据库,其中创建了“不需要的”表但为空。如果您真的根本不想要这些表,只需在加载完成后删除空表即可。
对于多个表,您可以执行如下操作:
sed '/INSERT INTO `TABLE1_TO_SKIP`/d' DBdump.sql | \
sed '/INSERT INTO `TABLE2_TO_SKIP`/d' | \
sed '/INSERT INTO `TABLE3_TO_SKIP`/d' > reduced.sql
有一个“陷阱” - 注意转储中可能包含“INSERT INTO TABLE_TO_SKIP”的过程。
评论
sed -r
sed -r '/INSERT INTO `(TABLE1_TO_SKIP|TABLE2_TO_SKIP)`/d' DBdump.sql > reduced.sql
TABLE_TO_SKIP
table_to_skip
-- Table structure for table <TABLE_TO_SKIP> DROP TABLE IF EXISTS <TABLE_TO_SKIP>; CREATE TABLE <TABLE_TO_SKIP> ( -- Dumping data for table <TABLE_TO_SKIP> LOCK TABLES <TABLE_TO_SKIP> WRITE;
这是我从mysql转储中排除一些表的脚本 当需要保留订单和付款数据时,我用它来恢复数据库
exclude_tables_from_dump.sh
#!/bin/bash
if [ ! -f "$1" ];
then
echo "Usage: $0 mysql_dump.sql"
exit
fi
declare -a TABLES=(
user
order
order_product
order_status
payments
)
CMD="cat $1"
for TBL in "${TABLES[@]}";do
CMD+="|sed 's/DROP TABLE IF EXISTS \`${TBL}\`/# DROP TABLE IF EXIST \`${TBL}\`/g'"
CMD+="|sed 's/CREATE TABLE \`${TBL}\`/CREATE TABLE IF NOT EXISTS \`${TBL}\`/g'"
CMD+="|sed -r '/INSERT INTO \`${TBL}\`/d'"
CMD+="|sed '/DELIMITER\ \;\;/,/DELIMITER\ \;/d'"
done
eval $CMD
它避免了表的 DROP 和 reCREATE 以及向此表插入数据。 此外,它还剥离了存储在 DELIMITER 之间的所有 FUNCTIONS 和 PROCEDURES;和分隔符 ;
对于任何处理.sql.gz文件的人;我发现以下解决方案非常有用。我们的数据库是 25GB+,我不得不删除日志表。
gzip -cd "./mydb.sql.gz" | sed -r '/INSERT INTO `(log_table_1|log_table_2|log_table_3|log_table_4)`/d' | gzip > "./mydb2.sql.gz"
感谢 Don 的回答和 Xosofox 的评论以及这篇相关文章:使用 zcat 和 sed 或 awk 编辑压缩的 .gz 文本文件
评论
log_table_*
-r
sed -r '/INSERT INTO.../d'
--regexp-extended
我不会在生产中使用它,但是如果我必须快速导入一些备份,其中包含许多较小的表和一个可能需要数小时才能导入的大怪物表,我很可能会“grep -v unwanted_table_name原始的.sql >减少.sql
然后 mysql -f < 减少.sql
评论
another_table_SALES_fk
有点老了,但想它可能还是会派上用场......
我喜欢@Don的答案(https://stackoverflow.com/a/26379517/1446005),但发现你必须先写到另一个文件,这很烦人......
在我的特殊情况下,这将花费太多时间和磁盘空间
所以我写了一个小 bash 脚本:
#!/bin/bash
tables=(table1_to_skip table2_to_skip ... tableN_to_skip)
tableString=$(printf "|%s" "${tables[@]}")
trimmed=${tableString:1}
grepExp="INSERT INTO \`($trimmed)\`"
zcat $1 | grep -vE "$grepExp" | mysql -uroot -p
这不会生成新的 SQL 脚本,而是将其直接管道传递到数据库
,它确实会创建表,只是不导入数据(这是我在大型日志表中遇到的问题)
除非您在转储期间忽略了这些表,否则在将数据传递给客户端之前,必须使用一些脚本或工具来筛选出您不想从转储文件中导入的数据。mysqldump --ignore-table=database.unwanted_table
mysql
下面是一个 bash/sh 函数,它将动态地(通过管道)从 SQL 转储中排除不需要的表:
# Accepts one argument, the list of tables to exclude (case-insensitive).
# Eg. filt_exclude '%session% action_log %_cache'
filt_exclude() {
local excl_tns;
if [ -n "$1" ]; then
# trim & replace /[,;\s]+/ with '|' & replace '%' with '[^`]*'
excl_tns=$(echo "$1" | sed -r 's/^[[:space:]]*//g; s/[[:space:]]*$//g; s/[[:space:]]+/|/g; s/[,;]+/|/g; s/%/[^\`]\*/g');
grep -viE "(^INSERT INTO \`($excl_tns)\`)|(^DROP TABLE (IF EXISTS )?\`($excl_tns)\`)|^LOCK TABLES \`($excl_tns)\` WRITE" | \
sed 's/^CREATE TABLE `/CREATE TABLE IF NOT EXISTS `/g'
else
cat
fi
}
假设您创建了一个转储,如下所示:
MYSQL_PWD="my-pass" mysqldump -u user --hex-blob db_name | \
pigz -9 > dump.sql.gz
并希望在导入之前排除一些不需要的表:
pigz -dckq dump.sql.gz | \
filt_exclude '%session% action_log %_cache' | \
MYSQL_PWD="my-pass" mysql -u user db_name
或者,您可以在导入数据库之前通过管道进入文件或任何其他工具。
除了本主题中的重要答案之外,可能是您的 .sql 文件没有每行都包含以下内容的 INSERTS:
INSERT INTO `log`
但它们实际上是这样插入的:
LOCK TABLES `log` WRITE;
INSERT INTO `log` (`id`, `data`)
VALUES
(1,'The log content'),
(2,'The log content'),
(3,'The log content'),
(4,'The log content')
UNLOCK TABLES;
您需要排除 and next 之间的所有内容LOCK TABLES `log` WRITE;
UNLOCK TABLES;
gzip -dc "$1" | sed \
-e '/LOCK TABLES `log` WRITE;/,/^UNLOCK TABLES/d;' \
-e '/LOCK TABLES `some_other_table` WRITE;/,/^UNLOCK TABLES/d;' \
| gzip > reduced_$(date '+%F_%T').sql.gz
把它放在你电脑上某个地方的reduce_db.sh里,每次你需要它时,你都会这样执行它
bash /folder/to/reduce_db.sh /path/to/big_db_file.sql.gz
很高兴知道,仅排除数据库中没有其他数据依赖的数据。否则,您的缩减数据库最终会不一致。
根据其他答案,我创建了一个 BASH 脚本:
https://gist.github.com/martin-rueegg/e247d99cc7402a4f1456c059c5d050ac
例子
显示将要过滤的内容:
$ mysql_filter_tables --show "log" $ mysql_filter_tables --show "%session%" "action_log" "%_cache" $ mysql_filter_tables --show -- "-h" # in case your table name is "-h"
纯SQL文件的用法:
$ mysql_filter_tables "log" <big.sql >clean.sql $ cat big.sql | mysql_filter_tables "log" >clean.sql
将普通 SQL 转储导入 mysql:
$ MYSQL_PWD=secret mysql_filter_tables -i big.sql "%_cache" | mysql -u user -D database
如果源被压缩:
$ mysql_filter_tables -i big.sql.zip --unzip -o clean.sql "%session%" "%_cache" $ mysql_filter_tables -i big.sql.gz --gunzip -o clean.sql "%session%" "%_cache"
更多选项
Command Options:
--show
show generated sed command, rather than executing it
-i | --input file
read from file, rather than standard input
-o | --output file
write result to file, rather than standard output
-f | --force
overwrite output file, if exists
-u | -ui | --unzip
unzip input stream. Use with -i to read from file
-z | -zo | --zip
zip ouput stream. Use with -o to write to file
-g | -gi | --gunzip
gunzip input stream. Use with -i to read from file
-G | -go | --gzip
gzip ouput stream. Use with -o to write to file
Info Options:
-h|--help show help
-V|--version show version
-1|--one-line show a one-liner that can be easily used in other scripts.
(Does not support any info options, except -V)
--copyright show copyright, license, and credits
--credits show copyright, license, and credits
--license show copyright, license, and credits
安装
从 github.com 下载文件
$ wget https://gist.github.com/martin-rueegg/e247d99cc7402a4f1456c059c5d050ac/raw/mysql_filter_tables.sh
为了您自己的安全,检查文件
获取文件,然后使用 shell 中的函数,或者......
$ source mysql_filter_tables.sh $ mysql_filter_tables --help
...将文件标记为可执行文件并将其用作脚本
$ chmod a+x mysql_filter_tables.sh $ ./mysql_filter_tables.sh --help
依赖
bash
sed
,cat
zip
,unzip
gzip
,zcat
评论