我有一个ubuntu服务器(2x 3.0Ghz四核,16GB ram和15k sas驱动器上的raid 1)运行一个普通的LAMP堆栈,其中大约5个客户端将第二个连接到php脚本。客户端传递一小部分信息,并在MySQL数据库中更新数据。
在服务器的后台,我有一个php脚本,每秒检查一次数据并更新数据库。
只有一些记录被反复更新,未插入,因此表格大小非常小(最多4行)。
也就是说,我通常会打开一个ssh会话,观察后台脚本的运行速度。经过一个月的直接运行SELECT和UPDATE查询大约需要100微秒(.0001秒),突然UPDATE开始每个查询花费20000+微秒(。02秒),无论使用什么数据库,使用或更新了哪个列(我重新启动了所有的东西,包括服务器,删除了我的所有数据库(只有我创建的数据库,而不是系统数据库),阻止了客户端,从控制台mysql和PhpMyAdmin运行查询,结果是同样的。
以下是一个示例,从没有加载的控制台或连接到服务器的客户端运行:
mysql> CREATE DATABASE `test` /*!40100 DEFAULT CHARACTER SET utf8 */;
Query OK, 1 row affected (0.00 sec)
mysql> CREATE TABLE `test` (
`idtest` int(11) NOT NULL AUTO_INCREMENT,
`field1` varchar(64) NOT NULL,
`field2` varchar(64) NOT NULL,
`field3` int(11) NOT NULL,
PRIMARY KEY (`idtest`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.14 sec)
mysql> INSERT INTO `test`.`test` (`idtest`, `field1`, `field2`, `field3`) VALUES (NULL, 'Testing', 'None', '0');
Query OK, 1 row affected (0.02 sec)
mysql> SELECT * FROM test;
+--------+---------+--------+--------+
| idtest | field1 | field2 | field3 |
+--------+---------+--------+--------+
| 1 | Testing | None | 0 |
+--------+---------+--------+--------+
1 row in set (0.00 sec)
mysql> UPDATE `test`.`test` SET `field3` = '1' WHERE `test`.`idtest` = 1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
从上面的示例中看,INSERT也会受到影响。我已经在另一台服务器上运行了大约1/10资源的相同查询,并按预期在100到200微秒内运行查询。我怀疑它与InnoDB缓存有关,但我可能错了。
以下是服务器和MySQL的一些信息:
负载平均值:平均负载:0.04,0.04,0.05
服务器:通过UNIX套接字的Localhost
服务器类型:MySQL
服务器版本:5.6.28-0ubuntu0.15.04.1 - (Ubuntu)
协议版本:10
用户:root @ localhost
服务器字符集:UTF-8 Unicode(utf8)
和
mysql> SHOW VARIABLES LIKE '%query%';
+------------------------------+-----------------------------------+
| Variable_name | Value |
+------------------------------+-----------------------------------+
| binlog_rows_query_log_events | OFF |
| ft_query_expansion_limit | 20 |
| have_query_cache | YES |
| long_query_time | 10.000000 |
| query_alloc_block_size | 8192 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 16777216 |
| query_cache_type | OFF |
| query_cache_wlock_invalidate | OFF |
| query_prealloc_size | 8192 |
| slow_query_log | OFF |
| slow_query_log_file | /var/lib/mysql/xxxxx-slow.log |
+------------------------------+-----------------------------------+
13 rows in set (0.00 sec)
和
mysql> SHOW VARIABLES LIKE '%cache%';
+--------------------------------+----------------------+
| Variable_name | Value |
+--------------------------------+----------------------+
| binlog_cache_size | 32768 |
| binlog_stmt_cache_size | 32768 |
| have_query_cache | YES |
| host_cache_size | 279 |
| innodb_disable_sort_file_cache | OFF |
| innodb_ft_cache_size | 8000000 |
| innodb_ft_result_cache_limit | 2000000000 |
| innodb_ft_total_cache_size | 640000000 |
| key_cache_age_threshold | 300 |
| key_cache_block_size | 1024 |
| key_cache_division_limit | 100 |
| max_binlog_cache_size | 18446744073709547520 |
| max_binlog_stmt_cache_size | 18446744073709547520 |
| metadata_locks_cache_size | 1024 |
| query_cache_limit | 1048576 |
| query_cache_min_res_unit | 4096 |
| query_cache_size | 16777216 |
| query_cache_type | OFF |
| query_cache_wlock_invalidate | OFF |
| stored_program_cache | 256 |
| table_definition_cache | 615 |
| table_open_cache | 431 |
| table_open_cache_instances | 1 |
| thread_cache_size | 8 |
+--------------------------------+----------------------+
24 rows in set (0.00 sec)
的my.cnf:
[mysqld]
innodb_autoinc_lock_mode=0
最后:
ubuntu@xxxxx:~$ df
Filesystem 1K-blocks Used Available Use% Mounted on
udev 8202368 0 8202368 0% /dev
tmpfs 1642808 9600 1633208 1% /run
/dev/mapper/xxxxx--vg-root 53035144 7827988 42490076 16% /
tmpfs 8214020 0 8214020 0% /dev/shm
tmpfs 5120 0 5120 0% /run/lock
tmpfs 8214020 0 8214020 0% /sys/fs/cgroup
/dev/sda1 240972 112893 115638 50% /boot
tmpfs 1642808 0 1642808 0% /run/user/1000
有什么想法吗?提前感谢您的帮助!
更新修改
鉴于问题非常奇怪且突然发生,我开始怀疑它可能与硬件有关。
我从服务器中彻底清除了MySQL并从存储库重新安装,它对这种情况没有影响。我正在使用Perc6i上的两个15k sas驱动器进行突袭1 - 我将从那里开始。这可能会导致比StackOverflow更多的ServerFault问题。我会在做了更多的挖掘之后再回来报告。
答案 0 :(得分:0)
如果它突然开始花费更长时间,我会想到几件事。
我不会继续谈论明显的事情,比如可以依赖的锁定机制来实现同步更新。
我认为OFFHAND你已经越过了一个文件大小阈值,你现在需要,例如,双间接磁盘块寻址而不是单间接块寻址。这意味着以逻辑顺序获取下一个磁盘块的每个单独调用将会慢得多。每一个实际的I / O都会受到惩罚。我指的是ACTUAL I / O,就像熄灭并触及磁盘块哈希队列的东西,这需要(在某些时候)任务磁盘控制器,而不仅仅是说read()和拉取已经预取的数据。最后一个磁盘I / O.
这只是猜测。
你真的很不高兴20,000 usec = 0.2毫秒?
答案 1 :(得分:0)
如果您想提高更新速度,请考虑使用char instead of varchar字段,并在where子句中用于比较的字段上创建unclustered indexes。
此外,不要通过运行一个查询来衡量您的更新速度,因为在更新查询中,如果您有机械硬盘驱动器,spin up time可能会影响结果。 Windows可以缓存数据库文件并从ram提供数据。禁用superfetch服务和run loops以测试旋转延迟。