我有一个 (KVM) Debian 8 VM 服务器,它在本地运行 MySQL 5.5.58 和 PHP7.1 我有一台类似的机器(Vagrant VM、Debian 8、VirtualBox)。在本地,如果我将迁移转储到 SQL 文件并导入 SQL 文件,则迁移运行时间不到 20 秒,大约需要 2-3 秒。
但是,在 (KVM) Debian 8 VM 服务器上迁移需要 10-20 分钟。我尝试过增加 CPU 数量和 RAM,但没有效果。
然而,有两件事可以极大地提高性能,但仍然不能真正使用:
- 将迁移文件转换为原始 SQL 并运行,大约需要 20-50 秒。
- 设置
innodb_flush_log_at_trx_commit=0
并运行迁移,这会将迁移运行时间减少到大约 4-5 分钟,但仍然不可用。
my.cnf
[mysqld]
sync_binlog = 0
federated = 1
innodb_use_sys_malloc = 0
innodb_file_per_table = 1
innodb_stats_on_metadata = 0
innodb_buffer_pool_instances = 1
query_cache_type = 0
innodb_buffer_pool_size = 1G
innodb_log_file_size = 768M
innodb_flush_log_at_trx_commit = 2
innodb_flush_method = O_DIRECT
user = mysql
pid-file = /var/run/mysqld/mysqld.pid
socket = /var/run/mysqld/mysqld.sock
port = 3306
basedir = /usr
datadir = /var/lib/mysql
tmpdir = /tmp
lc-messages-dir = /usr/share/mysql
skip-external-locking
bind-address = 127.0.0.1
key_buffer = 16M
max_allowed_packet = 16M
thread_stack = 192K
thread_cache_size = 8
myisam-recover = BACKUP
#max_connections = 100
#table_cache = 64
#thread_concurrency = 10
query_cache_limit = 1M
query_cache_size = 16M
文件系统:
Filesystem Size Used Avail Use% Mounted on
/dev/vda 32G 6.0G 25G 20% /
udev 11M 0 11M 0% /dev
tmpfs 422M 17M 406M 4% /run
tmpfs 1.1G 0 1.1G 0% /dev/shm
tmpfs 5.3M 0 5.3M 0% /run/lock
tmpfs 1.1G 0 1.1G 0% /sys/fs/cgroup
tmpfs 211M 0 211M 0% /run/user/2031
我测试和检查的内容:
- 确保我使用的所有内容与本地 myqsl、php、composer 包的版本相同,这里没有差异。
- 测试了虚拟机的磁盘 FIO 速度,以确保这里不存在瓶颈,尝试写入/读取单个大文件以及数千个小文件,全面获得高速(磁盘为 SSD,运行状况良好)。
- 在迁移过程中添加了额外的核心并监控 CPU 使用情况,但数量非常小。
- 从
Migrator
定时执行 LaravelgetUp
方法。特别定时从磁盘读取迁移文件、创建新类并执行查询,每次迁移似乎都在执行 <1 秒使用 microtime(true)
。 - 检查了 mysql 慢速查询,没有发现任何慢速查询,迁移实际上是非常基本的
CREATE TABLE
语句。 - 尝试安装 MySQL 5.7,但没有任何改进。
- 尝试增加 MySQL 池和日志 RAM 大小。
- 确保我使用的是 InnoDB。
注意:在我使用安装在主机上的 MySQL 进行测试的所有使用 MySQL 的方式中都会发生这种情况。我安装了 docker mysql 同样的问题。我在同一问题中安装了 vagrant 实例和 mysql。
这个innodb_flush_log_at_trx_comit
似乎最有区别,表明我搞砸了mysql的一些东西,只是不知道为什么。 迁移每个都在其自己的事务中运行,似乎有些东西导致此处等待时间,不确定还需要检查什么。
最佳答案
您的原始 SQL 中很可能有一堆 INSERT
查询。
编辑 MySQLDump 生成的 SQL 中确实有很多插入。填充测试 dbms 通常是通过版本控制的 SQL 文件完成的。 Here's some q&a about doing it in docker .
通过将 START TRANSACTION;
放在开头并将 COMMIT;
放在事务中,将每个系列的 100 个左右的查询(实际数量并不重要)包装起来结束。这将消除自动提交带来的困惑。您将得到一个如下所示的 SQL 文件:
START TRANSACTION;
INSERT ...;
... (more inserts)
INSERT ...;
COMMIT;
START TRANSACTION;
INSERT ...;
... (more inserts)
INSERT ...;
COMMIT;
START TRANSACTION;
INSERT ...;
... (more inserts)
INSERT ...;
COMMIT;
避免使用 innodb 参数;默认值通常都很好,只需要针对较大的动态负载进行更改。
并且不要指望您的虚拟机的性能与笔记本电脑一样好。服务器比笔记本电脑更快的日子已经一去不复返了(对于我们大多数人来说)。
关于php - 迁移速度非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47348927/