我正在将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倍。
query_cache_size = 512M
真的很糟糕对于来自转储的每个INSERT
,必须清除查询缓存中有关表的任何条目。当然,没有,但代码太愚蠢,无法实现它。
要么关闭负载的QC,要么将尺寸减小到不超过50M。
如果您使用的是MyISAM,请不要。转移到InnoDB。
恢复mysqldump文件自然只使用一个线程,并按顺序导入数据,一个表一个接一个地导入。
我建议使用mysqldump --tab
(带有其他选项)将每个表转储为两个文件:一个用于模式定义的.sql文件和一个用于原始数据的文本文件。
然后,您可以使用mysqlimport --use-threads=4
(使用其他选项来处理所有文件)导入数据文件(在创建所有表之后),以便您可以同时加载多个表。
此方法还会跳过对导入的所有SQL使用,从而减少了大量的SQL解析开销。
您还可以尝试使用mydumper & myloader,它是开源社区工具,支持转储和恢复的并行操作。我不知道它是否作为预先构建的二进制文件可用,您可能必须从源代码构建它以获取最新版本。
最快的恢复解决方案是使用Percona XtraBackup进行物理备份。恢复根本不需要导入,只需将文件放在适当位置并启动MySQL服务器即可。但是无法将数据导入现有的MySQL服务器。恢复物理备份需要关闭MySQL服务器并覆盖已存在的任何数据。