如何在 InnoDB 引擎中使用插入延迟并为插入语句使用更少的连接?

Sha*_*ank 11 mysql innodb memory prepared-statement php

我正在开发一个涉及大量数据库写入的应用程序,大约 70% 的插入和 30% 的读取。这个比率还包括我认为是一次读取和一次写入的更新。通过插入语句,多个客户端通过下面的插入语句在数据库中插入数据:

$mysqli->prepare("INSERT INTO `track` (user, uniq_name, ad_name, ad_delay_time ) values (?, ?, ?, ?)");
Run Code Online (Sandbox Code Playgroud)

问题是我应该使用insert_delay还是使用mysqli_multi_query机制,因为 insert 语句在服务器上使用 ~100% cpu。我在我的数据库上使用 InnoDB 引擎,所以插入延迟是不可能的。服务器上的插入是 ~36k/hr 和 99.89% 读取,我也在使用 select 语句在单个查询中检索数据七次,这个查询在服务器上执行需要 150 秒。我可以使用什么样的技术或机制来完成这项任务?我的服务器内存是 2 GB,我应该扩展内存吗?。看看这个问题,任何建议将不胜感激。

表的结构:

+-----------------+--------------+------+-----+-------------------+----------------+
| Field           | Type         | Null | Key | Default           | Extra          |
+-----------------+--------------+------+-----+-------------------+----------------+
| id              | int(11)      | NO   | PRI | NULL              | auto_increment |
| user            | varchar(100) | NO   |     | NULL              |                |
| uniq_name       | varchar(200) | NO   |     | NULL              |                |
| ad_name         | varchar(200) | NO   |     | NULL              |                |
| ad_delay_time   | int(11)      | NO   |     | NULL              |                |
| track_time      | timestamp    | NO   | MUL | CURRENT_TIMESTAMP |                |
+-----------------+--------------+------+-----+-------------------+----------------+
Run Code Online (Sandbox Code Playgroud)

我的数据库当前状态,它显示 41k 插入(写入),这对我的数据库来说非常慢。

数据库状态

Rol*_*DBA 12

由于您有更多的写入然后读取,我想推荐以下内容

InnoDB 的适当调优将是关键

缓冲池(由innodb_buffer_pool_size 调整大小

由于InnoDB 不支持 INSERT DELAYED,因此使用大型 InnoDB 缓冲池是最接近 INSERT DELAYED 的方法。所有 DML(插入、更新和删除)都将缓存在 InnoDB 缓冲池中。写入的事务信息会立即写入重做日志(ib_logfile0、ib_logfile1)。在缓冲池中发布的写入通过 ibdata1(用于二级索引的插入缓冲区,双写入缓冲区)定期从内存刷新到磁盘。缓冲池越大,可以缓存的 INSERT 数量就越大。在具有 8GB 或更多 RAM 的系统中,使用 75-80% 的 RAM 作为 innodb_buffer_pool_size。在 RAM 非常少的系统中,为 25%(以适应操作系统)。

CAVEAT :您可以将innodb_doublewrite设置为 0 以进一步加快写入速度,但要冒数据完整性的风险。您还可以通过将innodb_flush_method设置为 O_DIRECT 以防止将 InnoDB 缓存到操作系统来加快速度。

重做日志(由innodb_log_file_size 调整大小

默认情况下,重做日志命名为 ib_logfile0 和 ib_logfile1,每个大小为 5MB。大小应该是 innodb_buffer_pool_size 的 25%。如果重做日志已经存在,在 my.cnf 中添加新设置,关闭 mysql,删除它们,然后重新启动 mysql

日志缓冲区(由innodb_log_buffer_size 调整大小

日志缓冲区在将更改刷新到重做日志之前保存 RAM 中的更改。默认为 8M。日志缓冲区越大,磁盘 I/O 就越少。处理非常大的事务时要小心,因为这可能会使 COMMIT 慢几毫秒。

访问多个 CPU

MySQL 5.5 和 MySQL 5.1 InnoDB 插件具有让 InnoDB 存储引擎访问多个 CPU 的设置。以下是您需要设置的选项:

  • innodb_thread_concurrency设置 InnoDB 可以保持打开的并发线程数的上限。通常建议将此设置为(2 X CPU 数)+ 磁盘数。去年,我从 Percona NYC 会议上第一手了解到,您应该将其设置为 0,以便提醒 InnoDB 存储引擎找到适合其运行环境的最佳线程数。
  • innodb_concurrency_tickets设置可以绕过并发检查而不受惩罚的线程数。达到该限制后,线程并发检查再次成为常态。
  • innodb_commit_concurrency设置可以提交的并发事务数。由于默认值为 0,因此不设置此项将允许同时提交任意数量的事务。
  • innodb_thread_sleep_delay设置 InnoDB 线程在重新进入 InnoDB 队列之前可以休眠的毫秒数。默认值为 10000(10 秒)。
  • innodb_read_io_threads(将此设置为 3000)和innodb_write_io_threads(将此设置为 7000)(均自 MySQL 5.1.38 起)为读取和写入分配指定数量的线程。默认值为 4,最大值为 64。将这些设置为 64。此外,将innodb_io_capacity设置为 10000。

升级到 MySQL 5.5

如果您有 MySQL 5.0,请升级到 MySQL 5.5。如果您有 MySQL 5.1.37 或更低版本,请升级到 MySQL 5.5。如果您有 MySQL 5.1.38 或更高版本并希望继续使用 MySQL 5.1,请安装 InnoDB 插件。这样,您就可以利用 InnoDB 的所有 CPU。


Ric*_*mes 2

INT(2) 仍然使用 4 个字节——也许您的意思是 TINYINT UNSIGNED?

setno 有多少个不同的值?如果它很小,则 KEY(setno) 将永远不会被使用。INSERTing 必须更新该索引;删除 KEY 会加速 INSERT 一些。

CHAR(10) --flag长度总是 10 个字符吗?那么用utf8呢?也许你可以使用标志 VARCHAR(10) CHARACTER SET ascii

批量插入——一次插入 100 个,运行速度提高 10 倍。(超过 100 就进入“收益递减”状态。)

自动提交的价值是什么?您是否将每个 INSERT 包装在 BEGIN...COMMIT 中?innodb_flush_log_at_trx_commit 的值是多少?