我正在写一个索引器,使用python,索引文件并将它们插入到数据库中。在它是单个进程之前,但是现在我使用4个并行进程进行多处理。每次文本提取之后,它将插入数据库并进行提交。
现在它遇到IO问题,主要IO问题不是我的过程,而是EXT4的jdb2,journeling系统。 在每个MySQL提交中,等待IO的时间为99.99%,并等待CPU。
我看到很多在互联网上有这个问题,他们的解决scheme是安装使用barrier = 0。 这将完全禁用日记? 我的服务器有UPS和诱惑去做,我应该吗?
在永续性和性能之间总会有一个折衷。
在ext4上使用MySQL时,barrier = 1的默认值确实会导致速度变慢,但是第一个操作不应该是禁用日志logging或打开data = writeback。
首先,如果弹性是非常重要的,那么电池支持RAID是非常值得的。
我select的安装选项,特别是在非电池支持的RAID上:
/dev/mapper/vg-mysql--data /var/lib/mysql/data ext4 defaults,noatime,nodiratime,barrier=1,data=ordered 0 0
这是故意不使用数据=回写,因为我不想冒险的文件系统损坏导致“旧数据出现在崩溃和日志恢复后的文件”(引用是从man mount )。
my.cnf中有关I / O相关设置的完整弹性的理想configuration是:
[mysqld] sync_binlog = 1 innodb_flush_log_at_trx_commit = 1
为了提高性能,我select了以下一系列权衡:
sync_binlog = 0 :这是第一个改变了完全弹性的MySQLconfiguration。 原因是它可以显着提高性能,尤其是在binlog_format=row (不幸的是Jira需要)的情况下。 我在集群中使用了足够的MySQL副本,如果binlog被损坏的情况下,我会做从另一个副本的二进制副本。 innodb_flush_log_at_trx_commit = 2 :完全符合ACID要求值为1,值为2“时,日志缓冲区会在每次提交时写入文件,但不执行刷新到磁盘的操作,但是,在值为2时,每秒也会刷新日志文件。请注意,由于进程调度问题,每秒一次的刷新不是100%保证。 (来自MySQL文档的引用) data=writeback 。 请注意,如果这是您的根文件系统,您还需要传递内核命令行选项。 我在coderwall上放了几个步骤。 innodb_flush_method各种值。 显示O_DIRECT可以提高某些工作负载的性能,但是这并不是一定能够在您的环境中工作的。 innodb_io_capacity ,并调整诸如innodb_adaptive_flushing , innodb_read_io_threads , innodb_write_io_threads , innodb_purge_threads和其他可能的设置等设置。 将数据库放在非日志文件系统上。 至less较大的服务器(oracle,sql server)具有自己的日志function(事务日志),并相应地优化其IO。 在单独的文件系统和磁盘上有日志和数据库,并依靠数据库内部function来处理错误的IO。 通常没有(更大的设置)文件系统的变化,除了写date,因为文件不扩大 – 他们将被生成与他们的“最后”的大小(好吧,pipe理员可以改变这一点),和变化是我所说的数据库级别的事务日志。
你也可能想告诉我们你的硬件层是什么。 大多数人低估IOPS是数据库的限制因素,认为小型光盘集合适合大型数据库。 虽然我们中的一些人在使用大量光盘的数据库上工作,因此可能会支持更多的IOPS。
很有可能你的I / O后端不能很好地处理负载。 你应该确保你的文件系统不logging数据。 我build议使用data=writeback,relatime,nobarrier参数来装载数据库的数据分区,作为第一个快速和肮脏的优化。
此外,从你的症状中推断,你显然没有使用你的控制器写caching。 您应确保在控制器上使用电池备份或闪存支持的写入caching,并启用它 – 这应该会显着提升性能,而不会大大增加数据丢失或损坏的风险。 请注意,在没有电池或闪存备份的情况下使用写入caching确实会增加数据丢失或损坏的风险 – 所以只能用于testing目的和/或如果可以承受损失。
这是一个老问题,但是我们在一个新的专用服务器上面对同样的问题(高IO等待,可怕的插入/更新速度),这个解决scheme直接解决了这个问题。
使用tune2fs -O "^has_journal" /dev/<drive>禁用日志loggingtune2fs -O "^has_journal" /dev/<drive>是最快的解决scheme,因为它消除了由于JDB2进程造成的IO等待。 但是,除非您有电池备份驱动器,否则不build议这样做,因为在发生故障时会丢失数据。 InnoDB表是安全的,如果你在MySQL中启用了doublewrite 。 但是.frm,日志等文件是不安全的。 我们尝试将这些文件移动到另一个驱动器(特别是bin日志),但jdb2 IO等待仍然存在。 所以它没有让我们很舒服。
data=writeback,relatime,nobarrier并没有帮助它加速写入/读取和在整个分区上禁用日志logging一样多。 ext4的更多选项在EXT4文档中 。
在我们的情况下真正的罪魁祸首是sync_binlog 。 我们在/etc/mysql/my.cnf设置为1 ,这是在杀死性能。
Percona在此validation 。 我们将其设置为默认值0 ,性能提高了500%以上。
你用什么数据库引擎来插入这些数据?
如果是MyISAM:在写入时必须locking整个表,所以运行并发的插入线程将会杀死任何系统,不pipe它有多强大。
确保你使用InnoDB来处理这些表格。
另外,与mysql没有直接关系,但是由于电力pipe理的积极性,一些HD有ext4的问题…当这种情况发生时,机器负载增加而没有任何明显的活动。
尝试禁用它。 首先检查你有什么价值(如果你需要把它放回去,而不重新启动),然后禁用它。
检查当前值:
hdparm -B /dev/sda
禁用它
hdparm -B 255 /dev/sda
(或任何你的HD)和testing。 可能对大多数问题没有帮助,但可能会帮助一些用户。 重新启动将重置该值,或者手动replace之前值为255的值。
如果有帮助,通过在启动时设置它,检查/etc/default/hdparm或/etc/hdparm.conf以获得更加永久的configuration。