InnoDB 瓶颈:放宽 ACID 以提高性能

Posted

技术标签:

【中文标题】InnoDB 瓶颈:放宽 ACID 以提高性能【英文标题】:InnoDB Bottleneck: Relaxing ACID to Improve Performance 【发布时间】:2012-05-14 13:04:52 【问题描述】:

在注意到我们的数据库已成为我们现场制作系统的主要瓶颈后,我决定构建一个简单的基准来查明问题的根源。

基准测试:我计算了将 InnoDB 表中的同一行增加 3000 次所需的时间,其中该行由其主键索引,并且正在更新的列不属于任何索引。我使用远程机器上运行的 20 个并发客户端执行这 3000 次更新,每个客户端都有自己独立的数据库连接。

我有兴趣了解为什么我进行基准测试的不同存储引擎 InnoDB、MyISAM 和 MEMORY 具有它们所做的配置文件。我也希望了解为什么 InnoDB 相比之下表现如此糟糕。

InnoDB(20 个并发客户端): 每次更新需要 0.175 秒。 所有更新均在 6.68 秒后完成。

MyISAM(20 个并发客户端): 每次更新需要 0.003 秒。 所有更新都在 0.85 秒后完成。

内存(20 个并发客户端): 每次更新需要 0.0019 秒。 所有更新都在 0.80s 之后完成。

考虑到并发性可能会导致这种行为,我还对单个客户端执行 100 次顺序更新进行了基准测试。

InnoDB: 每次更新耗时 0.0026 秒。

MyISAM: 每次更新耗时 0.0006 秒。

内存: 每次更新耗时 0.0005 秒。

实际机器是一个 Amazon RDS 实例 (http://aws.amazon.com/rds/),大部分是默认配置。

我猜答案是这样的:每次更新后 InnoDB fsyncs(因为每次更新都是符合 ACID 的事务),而 MyISAM 不支持,因为它甚至不支持事务。 MyISAM 可能在内存中执行所有更新,并定期刷新到磁盘,这就是它的速度接近 MEMORY 存储引擎的方式。如果是这样,有没有办法使用 InnoDB 来支持它的事务,但也许可以放松一些约束(通过配置),以便以一些持久性为代价更快地完成写入?

另外,随着客户端数量的增加,关于如何提高 InnoDB 性能的任何建议?它的扩展性显然比其他存储引擎差。

更新

我找到了https://blogs.oracle.com/mysql/entry/comparing_innodb_to_myisam_performance,这正是我要找的。设置 innodb-flush-log-at-trx-commit=2 允许我们在发生电源故障或服务器崩溃的情况下放宽 ACID 约束(每秒刷新一次磁盘)。这为我们提供了与 MyISAM 类似的行为,但我们仍然可以从 InnoDB 中提供的事务功能中受益。

运行相同的基准测试,我们看到写入性能提高了 10 倍。

InnoDB(20 个并发客户端): 每次更新需要 0.017 秒。 所有更新都在 0.98 秒后完成。

还有其他建议吗?

【问题讨论】:

myisam 在设计上不符合 ACID。 InnoDB 是。如果你放宽约束,那么它就不再符合 ACID,你最好不要使用 innodb。 正在使用交易......对吗?当事务完成时,InnoDB 必须执行硬件刷新以保证"D" in ACID。即使是快速的 ACID DB,在“标准”主轴磁盘上也限制在大约 30-50 个事务/秒。 (但是,每秒获得数千次更新并不难。这是有区别的。) 确实,我们不需要完全符合 ACID。但是,如果我们想要一种更弱的 ACI(没有 D)来实现事务隔离等功能怎么办?由于我们的数据不太敏感,而且我们将 Amazon RDS 与多可用区结合使用,因此我们不必担心罕见的崩溃和电源故障。 @BrainCore 考虑将这些信息(真的更多放在前面)以及交易的使用(或不使用)一起放在主帖中。跨度> 隔离,但不耐用?我想知道你在做什么。 【参考方案1】:

我找到了https://blogs.oracle.com/MySQL/entry/comparing_innodb_to_myisam_performance,这正是我要找的。设置 innodb-flush-log-at-trx-commit=2 允许我们在发生电源故障或服务器崩溃的情况下放宽 ACID 约束(每秒刷新一次磁盘)。这为我们提供了与 MyISAM 类似的行为,但我们仍然可以从 InnoDB 中提供的事务功能中受益。

运行相同的基准测试,我们看到写入性能提高了 10 倍。

InnoDB(20 个并发客户端):每次更新需要 0.017 秒。所有更新均在 0.98 秒后完成。

【讨论】:

【参考方案2】:

我们在我们的应用程序中进行了一些类似的测试,我们注意到如果没有显式打开事务,则每条 SQL 指令都会在事务中处理,这需要更多时间来执行。如果您的业务逻辑允许,您可以将多个 SQL 命令放在一个事务块中,从而减少总体 ACID 开销。在我们的案例中,我们通过这种方法获得了极大的性能提升。

【讨论】:

以上是关于InnoDB 瓶颈:放宽 ACID 以提高性能的主要内容,如果未能解决你的问题,请参考以下文章

InnoDB简介

InnoDB死锁示例

使用匿名函数瓶颈提高 matlab 代码的性能

Mysql中innodb和myisam

mysql

通过预加载单元格提高 UITableView 性能