问题
最近遇到 2 个超大 sql 文件导入,好一通折腾
文档在哪里
调优参数太多,文档都看不过来
找到这些参数也费劲,
-
ubuntu 在 /etc/mysql/mysql.conf.d/mysqld.cnf 中找到这个链接
...... # # The MySQL Server configuration file. # # For explanations see # http://dev.mysql.com/doc/mysql/en/server-system-variables.html
-
centos 7 在 /etc/my.cnf 中找到这个链接
# For advice on how to change settings please see # http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html
-
耐心去阅读文档中那么多参数,需要勇气!
最终我也是从这里 mysql使用多cpu抄来的
# wzh 20230814 # Set the number of CPUs to be used by MySQL # # to half of the total available CPUs innodb_thread_concurrency = 2 # # Set the number of buffer pool instances innodb_buffer_pool_instances = 2 # # # Set the size of the query cache query_cache_size = 64M # # wzh 20230814 bulk_insert_buffer_size = 2G innodb_log_buffer_size = 2G innodb_autoinc_lock_mode = 2 #
调优后 三种导入方式对比
-
方式一: 使用 mysql source 命令,直接导入一个大文件 (18G)
为了统计用时和绘画内部优化,将实际mysqldump 文件包含到 all.sql
# cat all.sql SET GLOBAL innodb_lru_scan_depth=256; set session sql_mode = 'ALLOW_INVALID_DATES'; SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0; show global variables like 'innodb_lru_scan_depth'; show variables like '%sql_mode%'; show variables like '%autocommit'; show variables like '%unique_checks'; show variables like '%foreign_key_checks'; select now(); -- one file 18G source /home/XXXdata/20191230_135112.sql; show global variables like 'innodb_lru_scan_depth'; show variables like '%sql_mode%'; show variables like '%autocommit'; show variables like '%unique_checks'; show variables like '%foreign_key_checks'; select now();
导入过程
mysql > tee out-20230816.txt mysql > source /home/XXXdata/all.sql
查看结果
# cat out-20230816.txt ...... | 2023-08-16 08:17:02 | ...... | 2023-08-16 14:26:40 |
总共耗时 6 小时 +
-
方式2⃣️: 使用shell 命令行后台任务,直接导入一个大文件 (18G)
为了统计用时和绘画内部优化,将实际mysqldump 文件包含到 all.sql
# cat all.sql 同前一个方式
shell 后台任务
# nohup mysql -uroot -pPassword@123 --default-character-set=utf8 --force zXXX< /home/zXXX/all.sql > /home/out-20230817.txt 2>&1 &
查看执行结果
# cat out-20230817.txt ...... 2023-08-16 21:08:52 ...... 2023-08-17 01:43:14
用时 大约5 小时
-
方式三:SQLDumpSplitter切割 sql 文件 ( 每个 2G),使用 mysql source 命令,
切割后的结果
# ls *.sql -l -rw-r--r--. 1 root root 2147482476 8月 10 14:13 20191230_135112_0.sql -rw-r--r--. 1 root root 2147482521 8月 10 14:15 20191230_135112_1.sql -rw-r--r--. 1 root root 2147482263 8月 10 14:17 20191230_135112_2.sql -rw-r--r--. 1 root root 2147482371 8月 10 14:19 20191230_135112_3.sql -rw-r--r--. 1 root root 2147481971 8月 10 14:21 20191230_135112_4.sql -rw-r--r--. 1 root root 2147481699 8月 10 14:24 20191230_135112_5.sql -rw-r--r--. 1 root root 2147482612 8月 10 14:25 20191230_135112_6.sql -rw-r--r--. 1 root root 2147482594 8月 10 14:27 20191230_135112_7.sql -rw-r--r--. 1 root root 959044232 8月 10 14:28 20191230_135112_8.sql -rw-r--r--. 1 root root 1096 8月 16 14:14 all.sql
all.sql
# cat all.sql SELECT DATABASE(); select now(); SET GLOBAL innodb_lru_scan_depth=256; set session sql_mode = 'ALLOW_INVALID_DATES'; SET autocommit=0; SET unique_checks=0; SET foreign_key_checks=0; show global variables like 'innodb_lru_scan_depth'; show variables like '%sql_mode%'; show variables like '%autocommit'; show variables like '%unique_checks'; show variables like '%foreign_key_checks'; -- 00 source /home/XXXdata/20191230_135112_0.sql ; -- 01 source /home/XXXdata/20191230_135112_1.sql ; -- 02 source /home/XXXdata/20191230_135112_2.sql ; -- 03 source /home/XXXdata/20191230_135112_3.sql ; -- 04 source /home/XXXdata/20191230_135112_4.sql ; -- 05 source /home/XXXdata/20191230_135112_5.sql ; -- 06 source /home/XXXdata/20191230_135112_6.sql ; -- 07 source /home/XXXdata/20191230_135112_7.sql ; -- 08 source /home/XXXdata/20191230_135112_0.sql ; -- ALL OK show global variables like 'innodb_lru_scan_depth'; show variables like '%sql_mode%'; show variables like '%autocommit'; show variables like '%unique_checks'; show variables like '%foreign_key_checks'; SELECT DATABASE(); select now();
导入过程
mysql > tee out-20230816.txt mysql > source /home/XXXdata/all.sql
查看结果
cat out-20230816.txt ...... | 2023-08-16 08:17:02 | ...... | 2023-08-16 13:15:21 |
总共耗时大约 5 小时
不调优,使用shell 命令行后台任务,直接导入一个大文件 (18G)
-
注释掉 my.cnf 中的调优, restart mysqld 服务
# cat /etc/my.cnf # wzh 20230814 # Set the number of CPUs to be used by MySQL # # to half of the total available CPUs # innodb_thread_concurrency = 2 # # Set the number of buffer pool instances #innodb_buffer_pool_instances = 2 # # Set the size of the query cache # query_cache_size = 64M # # wzh 20230814 # bulk_insert_buffer_size = 2G # innodb_log_buffer_size = 2G # innodb_autoinc_lock_mode = 2 # wzh 20230817 # default-time-zone='Asia/Shanghai' explicit_defaults_for_timestamp=true log_timestamps=SYSTEM
这就和安装完 mysql 5.7 之后,全部使用缺省值一样了
-
shell 后台任务
nohup mysql -uroot -pPassword@123 --default-character-set=utf8 --force zXXX< /home/zXXX/all.sql > /home/out-20230817.txt 2>&1 &
-
查看结果
cat /home/out-20230817.txt
...
2023-08-18 14:50:11
...
2023-08-18 19:43:37
大约 5 小时,对比前面调优没有多大改进?
原因分析
决定实际完成快慢的,是该进程的 CPU 占用时间( cputime ) ?
以下是中途记录的一段
# ps -eo pid,euid,euser,lstart,etime,cputime,cmd | grep mysql
...
1877 0 root Fri Aug 18 08:22:21 2023 01:20:06 00:00:59 mysql -uroot -px xxxxxxxxxx --default-character-set=utf8 --force zXXX
...
可以看到,本次运行时间 01:20:06 ,CPU 占用时间 00:00:59 ,说明效率很高!
之前曾经有过运行一晚上,实际 cputime 才 2 个小时,效率太低了!
总结
-
切割 SQL 文件并不能显著改善导入速度 (也许我切割到 2G 还是太大了,感觉应该 1G )
-
使用 shell 命令行 和 mysql source 命令要快大约 20%-30%
-
使用多 CPU 和增加缓存等办法,没有测出有明显效果
-
影响导入速度的还是导入过程中的错误忽略 sql_mode = 'ALLOW_INVALID_DATES' 和 autocommit 等优化
-
shell 命令行 加上 --force
-
不要同时执行 2 个或以上大任务,互相影响!
-
提前判断好需要的硬盘空间,不要等最后才知道 disk full ,前功尽弃!
查看磁盘空间
df -h
如果可以找到原始的数据库来源,查看数据库文件大小
$ sudo du -sh /var/lib/mysql/zXXX
26G /var/lib/mysql/zXXX