Lio*_*ion 6 mysql ubuntu vbulletin mariadb docker
我正在寻找 Web 应用程序的瓶颈,并发现 INSERT 查询的运行速度明显变慢,如下所示:
MariaDB [myforum]> insert into tag set tagtext='abc12345',dateline=unix_timestamp(),canonicaltagid=1234;
Query OK, 1 row affected (0.24 sec)
Run Code Online (Sandbox Code Playgroud)
这是通过将 安装mysql-client
在应用程序容器中以进行测试来完成的。对于这样一个简单的查询,240 毫秒似乎很长。我假设了一些 dns/网络问题。但是在 MariaDB 容器中直接运行查询时,我看到了类似的结果,其中使用-h 127.0.0.1
以下方法建立连接:
MariaDB [myforum]> insert into tag set tagtext='abc123',dateline=unix_timestamp(),canonicaltagid=1234;
Query OK, 1 row affected (0.251 sec)
Run Code Online (Sandbox Code Playgroud)
仅 INSERT 查询有效。SELECTs 和预期的一样快。奇怪的是,这似乎与 MariaDB Docker 安装有关:我在本地 XAMPP 安装上有相同的数据库,其中相同的查询速度很快:
MariaDB [myforum]> insert into tag set tagtext='abc123',dateline=unix_timestamp(),canonicaltagid=123;
Query OK, 1 row affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
我只能对表格本身进行有限的更改,因为它们来自 vBulletin(旧的专有论坛 CMS)。
我想知道为什么这些简单的查询如此之慢?
CREATE TABLE `tag` (
`tagid` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`tagtext` VARCHAR(100) NOT NULL DEFAULT '',
`dateline` INT(10) UNSIGNED NOT NULL DEFAULT '0',
`canonicaltagid` INT(10) UNSIGNED NOT NULL DEFAULT '0',
PRIMARY KEY (`tagid`),
UNIQUE INDEX `tagtext` (`tagtext`),
INDEX `canonicaltagid` (`canonicaltagid`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=4112
;
Run Code Online (Sandbox Code Playgroud)
version: '2'
volumes:
mysql-data:
services:
# Here is another service that access the db using dns name 'mariadb'
mariadb:
container_name: mariadb
image: mariadb:10.3
mem_limit: 3GB
restart: always
env_file:
- mariadb.env
volumes:
- ../dump.sql:/docker-entrypoint-initdb.d/dump.sql
- mysql-data:/var/lib/mysql
Run Code Online (Sandbox Code Playgroud)
# lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 18.04.3 LTS
Release: 18.04
Codename: bionic
# docker --version
Docker version 19.03.1, build 74b1e89
# docker-compose --version
docker-compose version 1.24.1, build 4667896b
Run Code Online (Sandbox Code Playgroud)
该服务器有一个带有两个企业硬盘的软件 raid 1,足够的 CPU 功率和内存 (32GB)。它目前没有用于任何其他应用程序,也没有来自用户的任何负载。所以我可以排除它的负载问题。
经过一番研究,我找到了有关InnoDB刷新参数的信息。特别innodb_flush_log_at_trx_commit
是默认设置为 1:
MariaDB [myforum]> show variables like '%innodb_flush%';
+--------------------------------+----------+
| Variable_name | Value |
+--------------------------------+----------+
| innodb_flush_log_at_timeout | 1 |
| innodb_flush_log_at_trx_commit | 1 |
| innodb_flush_method | O_DIRECT |
| innodb_flush_neighbors | 1 |
| innodb_flush_sync | ON |
| innodb_flushing_avg_loops | 30 |
+--------------------------------+----------+
Run Code Online (Sandbox Code Playgroud)
值 1 表示在每次提交时写入和刷新。所以我认为这可能会带来开销。此处发布了一个相当大的妥协,将其更改为 2。这将导致每次提交后写入日志文件,但每秒仅将日志刷新到磁盘一次。
对我来说,这极大地提高了写入性能:MySQL cli 显示 0.000 秒,而不是像以前那样高达约 300 毫秒。此外,受影响 Web 应用程序的 HTML 渲染时间从 300 - 700 毫秒减少到约 90 - 120 毫秒。
这样做的后果:在最坏的失败情况下,一秒钟的交易可能会丢失。对于非常敏感/重要的数据(例如金融交易)和/或存在大量写入,这可能是不可接受的。我认为在像我这样的大多数常见网络案例中,这是一个合适的修复方法,我在全局范围内更改了该值:
set global innodb_flush_log_at_trx_commit = 2;
Run Code Online (Sandbox Code Playgroud)
这里的技术文档证实了我的发现:
innodb_flush_log_at_trx_commit
为 Innodb 比 MyISAM 慢 100 倍而哭泣?您可能忘记调整该值。默认值 1 意味着每个更新事务提交(或事务外的每个语句)都需要将日志刷新到磁盘,这是相当昂贵的,特别是如果您没有电池备份缓存。许多应用程序,尤其是那些从 MyISAM 表移动的应用程序都可以使用值 2,这意味着不将日志刷新到磁盘,而仅将其刷新到操作系统缓存。日志仍然每秒刷新到磁盘,因此您通常不会丢失超过 1-2 秒的更新。值 0 速度稍快,但安全性稍差,因为即使 MySQL 服务器崩溃,您也可能会丢失事务。值 2 仅导致数据丢失并导致操作系统完全崩溃。
但是,我仍然愿意接受其他/更好的解决方案。这篇文章列出了一些其他技巧,但其中大多数都不适合我(服务器有足够的资源、专有软件……)。但他们可能会帮助其他有类似问题的人。
归档时间: |
|
查看次数: |
1871 次 |
最近记录: |