导入MySQL数据库很慢,但没有明显的瓶颈

时间:2018-02-20 17:28:57

标签: mysql performance

我将20 GB的数据库导入MySQL 5.7服务器。转储是在同一台服务器上进行的。操作系统是Ubuntu 16.04

问题在于,它的运行速度非常慢。

这是我的MySQL配置:

[mysqld]
#
# * Basic Settings
#
user        = mysql
pid-file    = /var/run/mysqld/mysqld.pid
socket      = /var/run/mysqld/mysqld.sock
port        = 3306
basedir     = /usr
datadir     = /nvme/mysql
tmpdir      = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking

innodb_buffer_pool_size = 18120M
innodb_lock_wait_timeout= 99999999
innodb_change_buffering=all
innodb_flush_log_at_trx_commit=0
innodb_log_file_size=1G
innodb_autoinc_lock_mode=2

#key_buffer     = 4048M
max_allowed_packet  = 1024M
thread_stack        = 256M
thread_cache_size       = 1024
# This replaces the startup script and checks MyISAM tables if needed
# the first time they are touched
myisam-recover-options  = BACKUP
query_cache_limit   = 4M
query_cache_size    = 512M

log_error = /var/log/mysql/error.log
expire_logs_days    = 10
max_binlog_size   = 1G

这是来自另一个文件的Mysqldump配置

[mysqldump]
quick
quote-names
max_allowed_packet  = 1024M

这是我用来创建转储的命令

mysqldump --order-by-primary --opt --max-allowed-packet=64M dbName | gzip > dbDump.sql.gz"

这一个导入它

pv dbDump.sql.gz | { echo "set sql_log_bin=0;SET autocommit=0;SET unique_checks=0;SET foreign_key_checks=0;"; zcat; \
> echo "SET unique_checks=1;SET foreign_key_checks=1;SET autocommit=1;COMMIT;";} | mysql -uuser -ppwd awesomeDb

使用autocommit = 1导入需要48分钟,autocommit = 0则需要53分钟。

现在是硬件。

I'm running an Intel 4690K on 3.5Ghz , 4 cores
32 gigs of RAM.
The Dump is located on a Samsung 850 SSD.
The Database has a dedicated m.2 NVMe SM961 128 drive. Write speeds in Crystalmark for randomized writes are ~200-300MBps.  

Mysqld的资源使用情况(由KSysGuard报告)

Ram is constantly on 20.5GB  
CPU is 15-19%, so it's not using a whole core. 
The NVMe drive is being written on at 10-40 MiBPS. (had the same speeds on the 850 250GB). It's performing 50-200 read accesses per second 

我尝试了MySQL服务器docs的所有解决方案。试过添加set sql_log_bin = 0; SET autocommit = 0; SET unique_checks = 0; SET foreign_key_checks = 0;在转储之前。但是数据库仍然需要很长时间才能导入。

我知道从服务器复制文件是最快的方法。但我的目标是加快转储导入。

我不知道瓶颈在哪里。因为明显 - 没有任何东西被最大化。

编辑输入:
DB Schema是大约200个表,有386个外键(和200个索引)。没有表有超过10M行,最大表的大小是2.3,2.0,1.3,1.3,0.9 GB。

编辑:
在测试期间始终禁用查询缓存。另外,今天我导入了一个12GB的DB(相同的DB,只是更小)。花了34分钟。虽然数据库本身几乎小了2倍。

2 个答案:

答案 0 :(得分:0)

query_cache_size    = 512M

非常糟糕。对于来自转储的每个INSERT,必须清除查询缓存中有关表的任何条目。当然,没有任何东西,但代码实在太愚蠢了。

关闭负载的QC,或将尺寸降低到不超过50M。

如果您使用的是MyISAM,请不要这样做。转移到InnoDB。

答案 1 :(得分:0)

恢复mysqldump文件自然只使用一个线程,并按顺序导入数据,一个接一个地导入数据。

我建议使用mysqldump --tab(以及其他选项)将每个表转储到两个文件中:一个用于模式定义的.sql文件和一个用于原始数据的文本文件。

然后,您可以使用mysqlimport --use-threads=4导入数据文件(在创建所有表之后)(使用其他选项来处理所有文件),这样您就可以同时加载多个表。

此方法还会跳过所有使用SQL的导入,从而减少了大量的SQL解析开销。

您也可以尝试使用mydumper & myloader,它们是支持转储和恢复并行操作的开源社区工具。我不知道它是否作为预先构建的二进制文件可用,您可能必须从源代码构建它以获取最新版本。

最快的恢复解决方案是使用Percona XtraBackup进行物理备份。恢复根本不需要导入,只需将文件放在适当位置并启动MySQL服务器即可。但数据导入现有的MySQL服务器是不可能的。恢复物理备份需要关闭MySQL服务器并覆盖已经存在的任何数据。