2012-06-12 39 views
2

我正在一个debian-64上运行一个专门的DB守护进程,内存64G,磁盘空间很大。它使用磁盘哈希表(mmaped),并使用正常的write()调用将实际数据写入文件。当进行大量更新时,mmap的很大一部分会变脏,并且页面缓存会尝试将其刷新到磁盘,从而产生大量随机写入,从而降低对数据文件进行常规(顺序)写入的性能。如何优先write()通过mmap更新(或延迟mmap页面缓存刷新)

如果有可能延迟页面缓存刷新mmaped区域性能会提高(我认为),因为脏页面的几个(或全部)更改将一次写入而不是每次更新一次(最差事实上,它当然会汇总很多变化)。

所以我的问题:是否有可能延迟页面缓存刷新内存映射区域?或者有可能优先考虑正规写作?还是有人有任何其他想法? madvise和posix_fadvise似乎没有任何区别...

回答

3

你可以玩在/proc/sys/vm可调。例如,增加dirty_writeback_centisecs中的值可以使pdflush的唤醒次数减少一些,增加dirty_expire_centiseconds,这样数据就可以保持更长的时间,直到它必须写出,并且增加dirty_background_ratio以允许更多的脏页在RAM必须保留之前保留在RAM中做完了。
请参阅here了解所有值的具体内容。

注意,这会影响到你的机器上过程,但看到你是如何运行一个庞大的数据库服务器,有机会,这是没有问题的,因为你不希望别的在同一台机器上运行无论如何。

当然这会延迟写入,但它仍不能完全解决与write竞争的脏页回写问题(尽管如果有很多更新,它可能会崩溃一些写入)。
但是:可以使用sync_file_range系统调用,迫使开始写出来的页面在给定范围上的“写”文件描述符(SYNC_FILE_RANGE_WRITE)。因此,虽然脏页面将在稍后的某个未知时间回写(并且具有更大的宽限期),但您可以手动启动对感兴趣的页面的回写。
这不给任何保证,但它应该只是工作。

务必绝对肯定地阅读文档,更好地阅读两遍。如果使用错误,sync_file_range可能很容易损坏或丢失数据。尤其是,如果您追加到文件中,则必须确保元数据保持最新并刷新,否则在“崩溃”情况下,“已成功编写”的数据将“丢失”。

+0

这听起来很合理(尽管我认为我也必须增加dirty_ratio),我会在接下来的几周内尝试一下,并让你知道结果。谢谢! –

+0

它的工作原理和减少磁盘I/O预期:) –

+0

@HugoWalter:很高兴听到:) – Damon

0

我会尝试mlock。如果你的mlock有关的存储器范围,它可能会防止发生刷新。完成后您可以munlock

+1

虽然mlock可能会工作,但它不是通过避免冲洗。这是因为fysical内存将坚持地址范围,所以页面在被刷新后(并且很长时间没有被引用)后不会被盗取。确切的问题当然是访问哈希表将是非常稀疏和虚假的:有可能某个页面很长时间不会被引用(并且会被LRU从核心中删除)。Mlock可能会工作(如果内存不太紧) – wildplasser

+0

问题不在于它需要从磁盘重新加载散列表的相关部分(散列表并不是那么稀疏和大,我尝试了一个场景其中一切都适用于RAM,包括数据),问题是页面实际写入操作会导致重要的磁盘I/O(因为它们经常变脏),这会减慢写入数据文件的速度(当然这是不可避免的,但问题是它是否可以减轻) –

+0

问题是在(好的)散列表中,访问模式总是分散的。在包含N个页面的散列表上发布N个更新,将会达到(2/3)\ * N个页面。只有约。 N/3页将不会被击中。避免这种情况的唯一方法是不使用mmap(或匿名/私有映射),并且发明一些其他方式将更新应用于磁盘文件。 – wildplasser