处于“更新”状态时查询速度经常变慢

vir*_*ent 7 mysql innodb replication performance

我有两个经常更新的表,一个是直接的UPDATE ..,另一个是直接的,INSERT .. ON DUPLICATE KEY UPDATE ...通常这些查询是即时的,但有时需要 0.1 秒到 1+ 秒,然后又是即时的几秒钟。

另一件事要注意,我有两个 MySQL 服务器(在同一个专用网络中)。所有选择查询(除了一两个)都在从站上执行,这里看到的插入当然在主站上。当数据库处于大负载下时,速度减慢最为明显。最后,我正在使用 xtradb(看看它是否有帮助),但在纯 MySQL 5.5 InnoDB 上发生了相同的行为。

-- CustomData
+-----------+---------+------+-----+---------+-------+
| Field     | Type    | Null | Key | Default | Extra |
+-----------+---------+------+-----+---------+-------+
| Server    | int(11) | NO   | PRI | NULL    |       |
| Plugin    | int(11) | NO   | PRI | NULL    |       |
| ColumnID  | int(11) | NO   | PRI | NULL    |       |
| DataPoint | int(11) | NO   |     | NULL    |       |
| Updated   | int(11) | NO   | MUL | NULL    |       |
+-----------+---------+------+-----+---------+-------+
Run Code Online (Sandbox Code Playgroud)

前任。几个查询:

mysql> insert into CustomData (Server, Plugin, ColumnID, DataPoint, Updated) VALUES ( 52707, 1, 1, 0, 1327093596) on duplicate key update DataPoint = 0 , Updated = 1327093596 ;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into CustomData (Server, Plugin, ColumnID, DataPoint, Updated) VALUES ( 52707, 1, 1, 0, 1327093596) on duplicate key update DataPoint = 0 , Updated = 1327093596 ;
Query OK, 0 rows affected (0.12 sec)

mysql> insert into CustomData (Server, Plugin, ColumnID, DataPoint, Updated) VALUES ( 52707, 1, 1, 0, 1327093596) on duplicate key update DataPoint = 0 , Updated = 1327093596 ;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into CustomData (Server, Plugin, ColumnID, DataPoint, Updated) VALUES ( 52707, 1, 1, 0, 1327093596) on duplicate key update DataPoint = 0 , Updated = 1327093596 ;
Query OK, 0 rows affected (0.00 sec)
Run Code Online (Sandbox Code Playgroud)

解释-

mysql> explain select * from CustomData where Server = 52707 and Plugin = 1 and ColumnID = 1 ;
+----+-------------+------------+-------+---------------+---------+---------+-------------------+------+-------+
| id | select_type | table      | type  | possible_keys | key     | key_len | ref               | rows | Extra |
+----+-------------+------------+-------+---------------+---------+---------+-------------------+------+-------+
|  1 | SIMPLE      | CustomData | const | PRIMARY,Cron  | PRIMARY | 12      | const,const,const |    1 |       |
+----+-------------+------------+-------+---------------+---------+---------+-------------------+------+-------+
Run Code Online (Sandbox Code Playgroud)

探查器(用于 0.12 秒查询)

mysql> show profile for query 56 ;
+----------------------+----------+
| Status               | Duration |
+----------------------+----------+
| starting             | 0.000062 |
| checking permissions | 0.000005 |
| Opening tables       | 0.000016 |
| System lock          | 0.000007 |
| init                 | 0.000011 |
| update               | 0.129531 |
| end                  | 0.000005 |
| query end            | 0.000012 |
| closing tables       | 0.000008 |
| freeing items        | 0.000017 |
| logging slow query   | 0.000001 |
| cleaning up          | 0.000036 |
+----------------------+----------+
Run Code Online (Sandbox Code Playgroud)

所有其他有问题的查询都非常相似。我没有注意到任何长时间运行的查询show processlist;

显示引擎 INNODB 状态(需要 10 个代表才能发布 >2 个链接,所以)- pastebin .com/raw.php?i=tdtZeTCJ

我要注意的最后一件事是,在给定的示例中,任何工作人员都只会INSERT .. ON DUPLICATE KEY在唯一的行上执行,而不是在同一行上(因此每个查询都针对不同的行)

提前致谢!

编辑:

我所有的数据都在 3G 左右,带有索引。缓冲池大小最初是 2G,但也尝试过 4G。

我的.cnf-

[mysqld]
datadir = /data/mysql
socket = /var/run/mysqld/mysqld.sock
user = mysql
bind-address = 10.10.1.7

log-slow-queries = mysql-slow.log
long_query_time = 5
log-queries-not-using-indexes

# Replication
server-id        = 1

# master
log-bin          = /var/log/mysql/mysql-bin.log
expire-logs-days = 10
binlog-do-db     = metrics
max_binlog_size  = 104857600
binlog_format    = MIXED

# slave
# replicate-do-db  = metrics
# read_only        = 1

# /Replication

skip-external-locking
sysdate-is-now

performance_schema

log-error=/var/log/mysql.log

default-storage-engine          = InnoDB

innodb_file_per_table           = 1
innodb_file_format              = barracuda

innodb_buffer_pool_size          = 4G
innodb_additional_mem_pool_size  = 10M
innodb_log_buffer_size           = 8M
innodb_flush_log_at_trx_commit   = 0
innodb_lock_wait_timeout         = 50
innodb_fast_shutdown             = 1
innodb_flush_method              = O_DIRECT
transaction_isolation            = READ-COMMITTED

max_connections                 = 4092
connect_timeout                 = 86400
wait_timeout                    = 86400
interactive_timeout             = 86400
max_allowed_packet              = 64M

open_files_limit                = 2048
table_cache                     = 2048
net_buffer_length               = 8K
query_cache_type                = 1
query_cache_size                = 16M
thread_cache                    = 100
thread_stack                    = 512K
tmpdir                          = /dev/shm
tmp_table_size                  = 64M

key_buffer_size                 = 64M
sort_buffer_size                = 512K
net_buffer_length               = 8K
read_buffer_size                = 256K
read_rnd_buffer_size            = 512K
myisam_sort_buffer_size         = 8M

[mysqldump]
quick
max_allowed_packet              = 16M
[mysql]
no-auto-rehash

[myisamchk]
key_buffer_size                 = 20M
sort_buffer_size                = 20M
read_buffer                     = 2M
write_buffer                    = 2M

[mysqlhotcopy]
interactive-timeout

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
Run Code Online (Sandbox Code Playgroud)

编辑2

innotop-

一个 2

我读到了间隙锁定 - 是否有可能是间隙锁定我的PluginColumnID列,忽略了 PK 是 3 列的事实以及我使用的是 READ-COMMITTED 所以它不应该是这样的事实?正如在 innotop 中看到的,有些是非常接近的,所以如果是这种情况,那么就会有很多锁

mysql> show indexes from CustomData;
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| Table      | Non_unique | Key_name | Seq_in_index | Column_name | Collation | Cardinality | Sub_part | Packed | Null | Index_type | Comment | Index_comment |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
| CustomData |          0 | PRIMARY  |            1 | Server      | A         |     1073724 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          0 | PRIMARY  |            2 | Plugin      | A         |     1879017 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          0 | PRIMARY  |            3 | ColumnID    | A         |     7516069 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          1 | Cron     |            1 | Plugin      | A         |          20 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          1 | Cron     |            2 | ColumnID    | A         |          20 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          1 | Cron     |            3 | Updated     | A         |     7516069 |     NULL | NULL   |      | BTREE      |         |               |
| CustomData |          1 | Updated  |            1 | Updated     | A         |     2505356 |     NULL | NULL   |      | BTREE      |         |               |
+------------+------------+----------+--------------+-------------+-----------+-------------+----------+--------+------+------------+---------+---------------+
Run Code Online (Sandbox Code Playgroud)

cron 键每 30 分钟只使用一次,现在甚至没有启用(以防它被调出)

Rol*_*DBA 4

您需要对 InnoDB 设置进行一些调整

调整#1:更大的 InnoDB 重做日志

由于我没有看到innodb_log_file_size,我假设你有默认的5M。由于你的 innodb_buffer_pool_size = 是 4G,所以你需要 1G 重做日志。

调整 #2:让 InnoDB 使用所有 CPU

InnoDB 开箱即用,并不使用所有 CPU。我很久以前写过一篇关于 InnoDB LEFT UNCONFIGURED 如何在旧版本中运行得更快的文章。我还写了关于 InnoDB 多核参与的文章:

说了这么多,以下是要做的调整

cp /etc/my.cnf /etc/my.cnf_old
Run Code Online (Sandbox Code Playgroud)

将此设置添加到 /etc/my.cnf

[mysqld]
innodb_log_file_size = 1G
innodb_io_capacity = 20000
innodb_read_io_threads = 5000
innodb_write_io_threads = 5000
Run Code Online (Sandbox Code Playgroud)

接下来,运行这些步骤

service mysql stop
mv /var/log/mysql/ib_logfile0 /var/log/mysql/ib_logfile0_old 
mv /var/log/mysql/ib_logfile1 /var/log/mysql/ib_logfile1_old
service mysql start
Run Code Online (Sandbox Code Playgroud)

现在,所有核心都支持InnoDB,并且有更多的事务隔离空间

试一试 !!!