在MySQL中,I/O延迟是否会导致简单更新花费数秒?
我的MySQL应用程序在运行一些在MySQL中,I/O延迟是否会导致简单更新花费数秒?,mysql,vps,disk-io,Mysql,Vps,Disk Io,我的MySQL应用程序在运行一些UPDATE、INSERT和DELETE查询时,性能很慢。在这个问题中,我将只讨论一个特定的更新,因为它足以说明问题: UPDATE projects SET ring = 5 WHERE id = 1 此更新通常足够快,大约0.2ms,但偶尔(足以成为问题)需要几秒钟。下面是日志的摘录(请看第四行): projects是一个InnoDB表,有6列类型INT和VARCHAR,17行和id上的索引。其他桌子也会发生这种情况,但这里我将重点放在这张桌子上。在尝试解决
UPDATE
、INSERT
和DELETE
查询时,性能很慢。在这个问题中,我将只讨论一个特定的更新
,因为它足以说明问题:
UPDATE projects SET ring = 5 WHERE id = 1
此更新通常足够快,大约0.2ms,但偶尔(足以成为问题)需要几秒钟。下面是日志的摘录(请看第四行):
projects
是一个InnoDB表,有6列类型INT
和VARCHAR
,17行和id
上的索引。其他桌子也会发生这种情况,但这里我将重点放在这张桌子上。在尝试解决问题时,我确保所有查询都是顺序的,因此这不是锁问题。上面的更新
是在事务上下文中执行的。服务器上的其他信息:
4096 bytes from . (vzfs /dev/vzfs): request=1 time=249.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=2 time=12.3 ms
4096 bytes from . (vzfs /dev/vzfs): request=3 time=110.5 ms
4096 bytes from . (vzfs /dev/vzfs): request=4 time=232.8 ms
4096 bytes from . (vzfs /dev/vzfs): request=5 time=294.4 ms
4096 bytes from . (vzfs /dev/vzfs): request=6 time=704.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=7 time=1115.0 ms
4096 bytes from . (vzfs /dev/vzfs): request=8 time=209.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=9 time=64.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=10 time=396.2 ms
- 具有4GB RAM(1GB)和12GB可用磁盘空间的VPS
- 百分之五点八(是五点七)
- MySQL 5.5.10(WAS5.0.x)
上面的“was”表示它在升级之前或之后都不工作
到目前为止我所尝试的,但都没有用:
4096 bytes from . (vzfs /dev/vzfs): request=1 time=249.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=2 time=12.3 ms
4096 bytes from . (vzfs /dev/vzfs): request=3 time=110.5 ms
4096 bytes from . (vzfs /dev/vzfs): request=4 time=232.8 ms
4096 bytes from . (vzfs /dev/vzfs): request=5 time=294.4 ms
4096 bytes from . (vzfs /dev/vzfs): request=6 time=704.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=7 time=1115.0 ms
4096 bytes from . (vzfs /dev/vzfs): request=8 time=209.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=9 time=64.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=10 time=396.2 ms
- 将提交时的innodb刷新日志设置为0、1或2
- 为binlog设置innodb锁定不安全开关
- 设置
定时\u互斥锁
打开或关闭
- 将
innodb\u flush\u方法
从默认更改为O\u DSYNC
或O\u DIRECT
- 将innodb_buffer_pool_size从默认值增加到600M,然后再增加到3000M
- 将innodb日志文件大小从默认值增加到128M
- 从源代码编译MySQL
- 运行
SHOW PROCESSLIST
,通知我状态为“更新”
- 运行
SHOW PROFILE ALL
,这说明几乎所有的时间都花在了“更新”上,在这一步中,没有多少时间花在CPU周期上,并且有许多自愿的上下文切换(如30)
- 监控
显示状态
以查看Innodb\u缓冲区\u池\u页面\u脏的更改
。正在刷新的脏页与缓慢的查询之间可能存在某种关系,但相关性尚不清楚
然后我决定用ioping
检查系统的I/O延迟。这是我的第一次VPS,所以我很惊讶看到这个结果:
4096 bytes from . (vzfs /dev/vzfs): request=1 time=249.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=2 time=12.3 ms
4096 bytes from . (vzfs /dev/vzfs): request=3 time=110.5 ms
4096 bytes from . (vzfs /dev/vzfs): request=4 time=232.8 ms
4096 bytes from . (vzfs /dev/vzfs): request=5 time=294.4 ms
4096 bytes from . (vzfs /dev/vzfs): request=6 time=704.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=7 time=1115.0 ms
4096 bytes from . (vzfs /dev/vzfs): request=8 time=209.7 ms
4096 bytes from . (vzfs /dev/vzfs): request=9 time=64.2 ms
4096 bytes from . (vzfs /dev/vzfs): request=10 time=396.2 ms
我会说,这很不稳定
说完这些,我问:
I/O延迟会偶尔影响MySQL性能吗?我一直认为,当您运行更新时,负责该连接的线程不会将数据刷新到磁盘或等待这样的刷新;它将立即返回,并在另一时间由另一个线程进行冲洗
如果不是磁盘I/O,除了租用专用服务器之外,还有什么我可以尝试的吗?
问题1)是的
要检查它,请编写2个应用程序:
测试用例1:每隔几分钟做一次,持续几个小时
UPDATE `projects` SET `ring` = 5 WHERE `id` = 1
UPDATE `projects` SET `ring` = 6 WHERE `id` = 1
UPDATE `projects` SET `ring` = 7 WHERE `id` = 1
UPDATE `projects` SET `ring` = 8 WHERE `id` = 2
测试用例2:将每分钟执行一次,持续几个小时
UPDATE `projects` SET `ring` = 5 WHERE `id` = 1
UPDATE `projects` SET `ring` = 6 WHERE `id` = 1
UPDATE `projects` SET `ring` = 7 WHERE `id` = 1
UPDATE `projects` SET `ring` = 8 WHERE `id` = 2
测试用例1应该有延迟,而测试用例2不应该有延迟
问题2)使用noSQL数据库。在云中托管VP时,您可能会遇到完全无法控制的问题
VPS受到运行它们的主机服务器的突发奇想的影响。例如,Rackspace云的CPU周期优先级根据VP的大小进行加权。VPS越大,应用程序运行顺畅的可能性就越大。如果您正在使用的主机上有一个更大的VPS,那么很有可能是由于负载过大。这很难说
你试过在你自己的机器上本地运行这个吗?如果它能在您自己的系统上完美运行,并且您需要有保证的性能,那么您最好的选择就是移动到专用服务器。您遇到了与VPS相关的IO问题。这不是MySQL的错
您是否有可能在Amazon或RDS上使用Elastic Block Store?它们都使用远程存储和IP协议层与存储进行通信;他们有时会有严重的滞后。我在回答我自己的问题时,根据你的回答收集了额外的数据
我用了两台通过无线网络连接的笔记本电脑。在笔记本A上,我
使用sshfs
挂载笔记本B的目录。然后我在笔记本上启动了
MySQL指定挂载的目录作为其数据目录。这应该
为MySQL提供非常慢的I/O设备。MySQL是从
innodb\u flush\u log\u at\u trx\u commit=0
我定义了3组查询,每组包括一个更新和一个选择查询
重复10000次,没有显式事务。这些实验是:
- US1SID:更新并选择同一表的特定行。同一排
在所有迭代中都使用了
- US1MID:更新并选择同一表的特定行。这场争吵是一场闹剧
在每次迭代中使用不同的方法
- US2MID:更新并选择不同表的行。在这种情况下,表
在实验过程中,被select读取的数据没有任何变化
每个集合都使用shell脚本运行了两次(因此计时比我原来问题中的慢),一次在正常情况下运行,另一次在执行以下命令后运行:
tc qdisc replace dev wlan0 root handle 1:0 netem delay 200ms
上述命令在通过wlan0传输数据包时增加了200ms的平均延迟
首先,这里是前99%最快更新和选择的平均时间,以及
底部1%更新并选择
| Delay: 0ms | Delay: 200ms |
| US1SID | US1MID | US2MID | US1SID | US1MID | US2MID |
| top99%u | 0.0064 | 0.0064 | 0.0064 | 0.0063 | 0.0063 | 0.0063 |
| top99%s | 0.0062 | 0.0063 | 0.0063 | 0.0062 | 0.0062 | 0.0062 |
| bot01%u | 1.1834 | 1.2239 | 0.9561 | 1.9461 | 1.7492 | 1.9731 |
| bot01%s | 0.4600 | 0.5391 | 0.3417 | 1.4424 | 1.1557 | 1.6426 |
很明显,即使在I/O性能非常非常差的情况下,MySQL仍然能够
执行大多数查询非常快。但是我最关心的是什么