与XAMPP相比,在MariaDB Docker容器中进行INSERT SQL查询的速度非常慢

时间:2019-09-02 19:33:39

标签: mysql docker ubuntu mariadb vbulletin

我一直在寻找Web应用程序的瓶颈,发现INSERT查询的运行速度明显慢得多,如下所示:

MariaDB [myforum]> insert into tag set tagtext='abc12345',dateline=unix_timestamp(),canonicaltagid=1234;
Query OK, 1 row affected (0.24 sec)

这是通过在应用程序容器中安装mysql-client进行测试来完成的。对于这样一个简单的查询,240ms似乎很长。我假设有一些DNS /网络问题。但是当直接在使用-h 127.0.0.1建立连接的MariaDB容器中运行查询时,我会看到类似的结果:

MariaDB [myforum]> insert into tag set tagtext='abc123',dateline=unix_timestamp(),canonicaltagid=1234;
Query OK, 1 row affected (0.251 sec)

仅执行INSERT查询。 SELECT的速度非常快。奇怪的是,这似乎与MariaDB Docker安装有关:我在本地XAMPP安装上具有相同的数据库,其中相同的查询速度很快:

MariaDB [myforum]> insert into tag set tagtext='abc123',dateline=unix_timestamp(),canonicaltagid=123;
Query OK, 1 row affected (0.00 sec) 

我只能对表本身进行有限的更改,因为这些更改来自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
;

Docker Compose文件

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

有关基础Docker主机服务器的系统信息

# 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

该服务器的软件RAID 1具有两个企业硬盘,足够的CPU能力和内存(32GB)。而且它目前尚未用于任何其他应用程序,也没有用户的负担。因此,我可以排除其负载问题。

1 个答案:

答案 0 :(得分:2)

经过一些研究,我发现了有关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       |
+--------------------------------+----------+

值1表示每次提交都进行写入和刷新。因此,我认为这可能会增加开销。通过将posted here更改为2,可以解决这个问题。这将导致在每次提交后写入日志文件,但每秒仅将日志刷新一次到磁盘。

对我来说,这可以大大提高写入性能:MySQL cli显示0.000秒,而不是以前的300秒。受影响的Web应用程序的HTML呈现时间也从300-700ms减少到了90-120ms。

其后果:在失败的最坏情况下,一秒钟的交易可能会丢失。对于非常敏感/重要的数据(例如财务交易)和/或存在大量写入操作,这可能是不可接受的。我认为在像我这样的最常见网络案例中,这是一个适合的解决方案,我在全球范围内更改了该值:

set global innodb_flush_log_at_trx_commit = 2;

here的技术文档证实了我的发现:

  

innodb_flush_log_at_trx_commit

     

难道Innodb比MyISAM慢100倍?您可能忘记调整此值。默认值1表示每次更新事务提交(或事务外部的每个语句)都需要将日志刷新到磁盘上,这非常昂贵,尤其是在没有电池备份缓存的情况下。许多应用程序,尤其是那些从MyISAM表中移出的应用程序,都可以使用值为2的值,这意味着不刷新日志到磁盘,而仅刷新到操作系统缓存。日志仍然每秒刷新到磁盘,因此您通常不会丢失超过1-2秒的更新时间。值0会快一些,但安全性会降低一些,因为即使MySQL Server崩溃,您也可能丢失事务。值2仅在完全操作系统崩溃的情况下导致数据丢失。

但是,我仍然愿意接受其他/更好的解决方案。 This post列出了其他一些提示,但其中大多数都不适合我(服务器拥有足够的资源,专有软件等)。但是他们可能会帮助其他有类似问题的人。