【问题标题】:Avoid SSD wear when using SQLite database in Node.js在 Node.js 中使用 SQLite 数据库时避免 SSD 磨损
【发布时间】:2018-04-16 23:03:00
【问题描述】:

我有一个 Node.js 应用程序,它大量使用 SQLite 数据库,我担心它可能会对我的 SSD 造成影响。

我的应用程序会定期更新有关连接到某个服务器的所有客户端的信息。我不想在这里详细介绍有关客户端和/或服务器的任何细节。

每 5 秒,它为每个连接的客户端执行一次INSERT OR REPLACE。新客户被插入,现有客户的数据被更新的数据替换。单个行包含大约 10kB 的数据,一次最多可以连接 5,000 个客户端(= 插入/替换 5,000 行)。

在任务管理器中,我可以看到空闲状态下大约 3MB/s 的磁盘使用率和更新发生时大约 6MB/s 的磁盘使用率。

我应该担心会磨损我的 SSD 吗?如果是这样,我怎样才能减少磨损?

租用服务器或构建冗余 RAID 等选项对我来说真的不可用,因此我正在寻找软件解决方案。我已经尝试将journal mode 设置为WALtemp store 设置为memory,但temp store 总是恢复为defaultWAL journal mode 在这方面似乎没有太大的影响。

我已经使用事务了,但恐怕还不足以解决问题。另一个明显的解决方案是降低频率,但这对我来说并不是一个真正的选择,因为我需要一个包含尽可能最新数据的数据库。

我知道有一个使用:memory: 的内存数据库选项,但我必须跨会话存储客户端数据。我需要在应用程序初始化时从磁盘加载现有的客户端数据,并且我还需要定期将数据库的当前状态保存到磁盘,以避免在断电、意外的 Windows 更新或类似情况下丢失数据。考虑到这些事件发生的可能性很小,例如,可以每小时将这些备份到磁盘一次。

有什么方法可以将数据库大部分时间保存在内存中,并且只在初始化期间将其与物理磁盘上的版本同步,然后每隔一小时左右同步一次?

【问题讨论】:

  • 我想如果您使用的是持久性数据库,您希望尽快将其刷新到磁盘,是吗?您可以在内存中运行 SQLite,但这不会违背您想要做的全部目的吗?真的,听起来好像您应该使用比 SQLite 更多的东西来协调所有连接之间的磁盘写入。
  • @Brad - 这是一个持久性数据库,但没有关键数据(密码等)。它主要用于跟踪客户上次在线的时间,有关他们连接的一些信息等。我使用这些数据来生成各种统计数据,但这些数据对服务器的功能都不是至关重要的。如果丢失一小时的数据,这并不是什么大问题。此外,正如我所提到的,数据库只能从 Node.js 应用程序中访问,因此磁盘上的数据库应该只真正用作备份和持久性。
  • 一些 SSD 有可用的诊断软件,可以告诉您剩余的磨损寿命。我认为你最好的第一件事就是在你跑了这么多之后看看你站在哪里。如果你还剩 98% 并且你已经跑了一段时间,那么你可能没有问题。如果你是 50%,那么你可能确实有问题。如果您介于两者之间,那么您可能需要进行一些计算才能知道它会持续多长时间。
  • 如果您真的需要为每个连接的客户端每 5 秒写入一次数据库,我会感到惊讶,但您没有详细说明我们确切知道建议什么。例如,您可以在缓存中维护数据,实际上每 5 分钟而不是每 5 秒将其写入数据库。这将使这些类型的写入减少 60 倍。
  • “磁盘使用情况”主要是读取。每分钟写入多少数据?

标签: node.js sqlite solid-state-drive


【解决方案1】:

只有在事务提交时才将更改的数据刷新到磁盘,因此最重要的是在单个事务中放入尽可能多的语句。 (你说你已经在这样做了。)
如果您想将更改的数据保留在内存中并稍后写入磁盘,只需稍后提交即可。

当使用 WAL 模式时,更改的页面会简单地附加到 -wal 文件中(而不是写入主 DB 文件中的随机位置)。这在 SSD 上更容易(尽管您会注意到速度差异很大),因此您应该启用 WAL 模式。

为了防止-wal 文件变得太大,SQLite 有时会将每个页面的最新版本移回主数据库文件(这称为checkpoint)。当达到一定数量的页面时,会发生这种情况automatically;要减少这些写入,请将auto-checkpoint interval 增加到尽可能大的值(取决于您拥有的可用空间),或者完全禁用它并手动执行检查点。

temp_store 设置无效,除非数据库确实需要写入临时文件。

如果每个步骤最终都修改了表中的大部分或所有行,则可以通过使用更大的page_size 来减少开销;尝试 64 KB。 (但如果您只更改一小部分行,更大的页面大小只会增加数据库的write amplification。)


500 GB 850 EVO guarantees 可承受 150 TBW(写入 TB)。 平均 2.3 MB/s,相当于两年多。

【讨论】:

  • 那么,WAL 是我最好的选择吗?拥有一个~100GB WAL 文件会改善这种情况吗?另外,检查点上的 WAL 文件会发生什么?当我尝试使用 WAL 模式时,该文件似乎总是留在那里,直到我关闭数据库连接,它的变化只会不断增长,而不会缩小。这是预期的行为吗? --- 有没有办法将数据库从文件加载到内存中,并且只有在手动请求时才将其同步到文件中? (“手动”是指来自setInterval() 或类似的东西)
  • 是的,我知道确实如此,但我认为当检查点完成时 WAL 文件会缩小。此外,稍后提交实际上可能会在一定程度上解决问题。另一方面,它会使实时读取数据库变得不可能,因此它并不是一个完美的解决方案。两年时间很短,但至少我知道我确实必须为此做点什么。
猜你喜欢
  • 2011-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多