数据库嵌入式数据库【免费下载链接】better-sqlite3The fastest and simplest library for SQLite3 in Node.js.项目地址https://gitcode.com/gh_mirrors/be/better-sqlite3点击查看免费下载在 Node.js 中通过 better-sqlite3 使用 SQLite 时Web 应用常见的并发读 并发写场景最容易暴露性能瓶颈。本文基于官方 性能指南系统讲解如何通过开启WAL 模式Write-Ahead Logging大幅提升读写并发性能深入剖析 WAL 模式下Checkpoint Starvation检查点饥饿的产生原理与解决方案并说明 better-sqlite3 内置 SQLite 在 WAL 模式下的持久性默认行为及其权衡取舍。读完本文你将掌握一套可直接落地的高并发 SQLite 调优方案并能独立应对 WAL 文件无限增长、数据安全性等实际问题。为什么并发场景需要 WAL 模式SQLite 默认的日志模式rollback journal即journal_mode DELETE在写入时会加写锁并阻塞读操作同时对磁盘做多次同步写。在 Web 应用中并发读写频繁交错这种串行化会显著拖慢整体吞吐。better-sqlite3 官方文档给出的建议非常明确同时从一个 SQLite 数据库进行并发读写时应开启 WAL 模式。一行代码即可完成切换db.pragma(journal_mode WAL);WAL 模式下写操作先把变更追加到独立的-wal文件中而非直接覆写主数据库文件读操作则可以与写操作并行进行互不阻塞。这让大多数 Web 应用获得极其快速的性能提升。这一点在项目自身的基准测试中得到了印证benchmark 文档 明确标注所有基准测试均在 WAL 模式下执行All benchmarks are executed in WAL modebenchmark/trials.js 中每个试跑的默认 pragma 即为journal_mode WAL与synchronous NORMAL只有在设置环境变量NO_WAL时才回退到journal_mode DELETE, synchronous FULL。可见 WAL 模式是 better-sqlite3 官方认可的默认性能基线。提示如果应用是高并发、每次返回数 MB 数据如视频或高并发写入如社交网站SQLite 本身的串行特性会让 WAL 也力不从心此时应改用 PostgreSQL 等完整 RDBMS——详见 README。pragma() 方法的使用细节db.pragma()由 lib/methods/pragma.js 实现其行为要点第一个参数必须是字符串journal_mode WAL第二个参数是可选的 options 对象默认返回结果行数组每个结果是一个对象传入{ simple: true }时返回单个标量值便于读取如journal_mode、cache_size这类单值 pragma底层通过prepare(PRAGMA source)编译执行因此多余的PRAGMA关键字如db.pragma(PRAGMA cache_size)会触发SQLITE_ERROR。对应的验证见 test/12.database.pragma.jsjournal_mode默认值为delete执行db.pragma(journal_mode wal)后读取返回wal同时该测试也验证了只读连接下尝试切换 WAL 会抛出SQLITE_READONLY错误test/12.database.pragma.js。因此开启 WAL 需要数据库连接拥有写权限且数据库文件所在目录可写用于创建-wal与-shm文件。WAL 模式需要权衡的几个缺点WAL 并非没有代价官方文档明确列出三点需要开发者知晓涉及 ATTACH 数据库的事务不具备跨库原子性WAL 模式下附加ATTACH的多个数据库各自保证事务原子性但作为一个整体集合并不原子。跨库的一致性需要应用层自行协调。极端情况下 WAL 文件可能遭遇 Checkpoint Starvation检查点饥饿详见下文专节。存在硬件/系统层面的限制部分平台或文件系统对 WAL 的支持有限例如某些网络文件系统、只读介质等部署前应确认运行环境是否适配。对大多数 Web 应用而言用这几点代价换取并发性能的大幅提升是划算的。Checkpoint StarvationWAL 文件无限增长的元凶它是什么Checkpoint starvation 指 SQLite 无法回收recycleWAL 文件的情况。正常情况下后台自动 checkpoint 会定期把-wal文件中的内容合并回主数据库文件并重置 WAL。但如果数据库上持续存在并发读checkpoint 无法取得完成合并所需的写权限WAL 文件就会无边界地增长最终导致磁盘占用失控、查询性能持续劣化。你是否会遇到官方给出了明确的判断标准如果不同时从多个进程或多个线程访问该数据库永远不会遇到此问题单连接串行访问不存在长读阻塞如果确实存在多进程/多线程并发访问且 WAL 文件过大时就需要人工干预。解决方案wal_checkpoint(RESTART)解决手段是当 WAL 文件增长到不可接受的大小时主动执行wal_checkpoint(RESTART)pragmadb.pragma(wal_checkpoint(RESTART));RESTART模式会先完成 checkpoint随后在第一个写事务处重置 WAL 文件从而回收空间。官方给出的监控示例是配合fs.stat定时轮询-wal文件大小超过阈值即触发setInterval(fs.stat.bind(null, foobar.db-wal, (err, stat) { if (err) { if (err.code ! ENOENT) throw err; } else if (stat.size someUnacceptableSize) { db.pragma(wal_checkpoint(RESTART)); } }), 5000).unref();实现要点拆解setInterval(..., 5000)每 5 秒检查一次通过fs.stat读取数据库文件名-wal即foobar.db-wal的大小err.code ENOENT表示 WAL 文件尚不存在正常现象忽略即可其他错误直接抛出当stat.size someUnacceptableSize阈值由你根据磁盘预算设定例如几百 MB时执行wal_checkpoint(RESTART).unref()让该定时器不阻止 Node.js 进程退出避免残留句柄。持久性Durability权衡NORMAL vs FULLbetter-sqlite3 内置的 SQLite 编译时启用了SQLITE_DEFAULT_WAL_SYNCHRONOUS1选项见 deps/defines.gypi 与 deps/download.sh其效果是WAL 模式下数据库默认使用 NORMAL 同步级别对应PRAGMA synchronous NORMAL。这一配置带来两个直接后果性能NORMAL在 WAL 模式下不需要在每个事务提交时同步刷新 WAL 文件到磁盘应用可获得极致的写入性能持久性付出了轻微的数据持久性损失——在 WAL 模式下NORMAL可能在系统崩溃/断电时丢失最近几次提交但不会损坏数据库结构这与每次提交都持久化的FULL有区别。官方文档明确给出了覆盖方式如果你对持久性有更高要求执行db.pragma(synchronous FULL);即可把同步级别提升为FULL换取更强的崩溃安全保证代价是写入性能下降。从源码层面看该编译选项确实作用于连接打开阶段SQLite 源码在初始化数据库文件头时会调用setDefaultSyncFlag(pBt, SQLITE_DEFAULT_WAL_SYNCHRONOUS1)见 deps/sqlite3/sqlite3.c且SQLITE_DEFAULT_WAL_SYNCHRONOUS默认继承SQLITE_DEFAULT_SYNCHRONOUS的值deps/sqlite3/sqlite3.c。better-sqlite3 将前者显式设为 1即 NORMAL使每个新数据库在 WAL 模式下自动获得高性能默认值——这正是 docs/compilation.md 所列捆绑编译配置中该选项的用意所在。注意synchronous NORMAL是WAL 模式下的默认值非 WAL 模式如 DELETE 日志模式下默认同步级别仍为FULL对应SQLITE_DEFAULT_SYNCHRONOUS2。这一点可从 test/12.database.pragma.js 的测试路径与 benchmark/trials.js 的默认配置组合得到印证。生产环境配置建议小结综合官方文档与仓库实现一个兼顾性能与可控性的实践组合是打开数据库后立即执行db.pragma(journal_mode WAL)让并发读写并行化对持久性要求高如金融、订单类数据的应用追加db.pragma(synchronous FULL)覆盖默认的 NORMAL 设置多进程/多线程共享同一数据库时用setInterval fs.stat监控-wal文件大小超过阈值执行db.pragma(wal_checkpoint(RESTART))牢记 WAL 模式不提供跨 ATTACH 数据库的集合级原子性跨库一致性需在应用层设计。如需复现性能收益可参照 docs/benchmark.md 的命令node benchmark在本地运行基准测试默认即以 WAL NORMAL 配置执行见 benchmark/trials.js并对比设置NO_WAL1时的性能差异关于编译选项的自定义方式可继续阅读 docs/compilation.md。赞分享数据库嵌入式数据库【免费下载链接】better-sqlite3The fastest and simplest library for SQLite3 in Node.js.项目地址https://gitcode.com/gh_mirrors/be/better-sqlite3点击查看免费下载相关推荐openPangu-Embedded-1B模型名称指定方法openPangu Embedded 1B模型名称指定方法 引言 在大语言模型Large Language Model, LLM部署和推理过程中模型名称数据库嵌入式数据库FastAPI Admin为你的FastAPI项目注入Django级管理能力FastAPI Admin为你的FastAPI项目注入Django级管理能力 你是否曾羡慕Django Admin那开箱即用的后台管理界面但又不想放弃Fas后端终极指南Casbin自动化策略保存的实时持久化与性能优化方案终极指南Casbin自动化策略保存的实时持久化与性能优化方案 Casbin作为一款强大的开源授权库支持ACL、RBAC、ABAC等多种访问控制模型其策略持后端认证鉴权上一篇如何用GetQzonehistory把几千条QQ空间老说说快速导出成Excel下一篇Super Mario 64 中的音频均衡器频率与音量调整创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考