دیتابیس ماندگار تو مرورگر با DuckDB-Wasm
خلاصهٔ کاملتر
از ۲۰۲۱ که DuckDB-Wasm اومد، یه محدودیت بزرگ داشت: هر چی میساختی تو هیپ Wasm میموند و با بسته شدن تب میپرید. برای نگه داشتن داده باید جدولها رو Parquet میکردی، بایتهاش رو تو IndexedDB میذاشتی و دفعهٔ بعد دوباره رجیسترشون میکردی. تو این پست اومده که مرورگرها از مارس ۲۰۲۳ به بعد OPFS دارن، یه فایلسیستم سندباکسشدهٔ مخصوص هر origin با خوندن و نوشتن random-access، و DuckDB-Wasm میتونه ازش به عنوان استوریج استفاده کنه.
کافیه موقع باز کردن دیتابیس به جای حالت پیشفرض :memory:، مسیر رو با پیشوند opfs:// بدی:
await db.open({
path: 'opfs://analytics.duckdb',
accessMode: duckdb.DuckDBAccessMode.READ_WRITE,
});نتیجه یه فایل .duckdb معمولی با write-ahead log و چکپوینته که ریلود صفحه و حتی ریاستارت مرورگر رو رد میکنه. اگه فایل رو از OPFS بکشی بیرون، با CLI یا کلاینت پایتون هم باز میشه.
مهمترین بخش پست همینجاست. DuckDB تراکنشهای کامیتشده رو اول به فایل .wal اضافه میکنه و فایل اصلی فقط موقع checkpoint آپدیت میشه: یا وقتی WAL از checkpoint_threshold که پیشفرضش ۱۶ مگابایته رد شه، یا وقتی دیتابیس تمیز بسته شه. رو دسکتاپ بسته شدن تمیز حالت عادیه، ولی تو مرورگر نه؛ کاربر تب رو میبنده، گوشی صفحهٔ بکگراند رو میکشه، در لپتاپ بسته میشه. نویسندهها میگن بعد از هر دسته نوشتنی که از دستش نمیدی، خودت CHECKPOINT بزن.
اگه حوصلهٔ دستهبندی نداری، با SET checkpoint_threshold = '0KB' بعد از هر دستور چکپوینت گرفته میشه که throughput نوشتن رو کم میکنه، ولی دیگه لازم نیست حواست به چکپوینت زدن باشه. WAL بزرگ هم باز شدن دفعهٔ بعد رو کند میکنه، چون قبل از اولین کوئری باید replay شه. همین پیشوند برای فایلهای داده هم کار میکنه: میشه خروجی یه aggregation رو به Parquet توی OPFS نوشت و بعداً خوندش، و با گزینهٔ opfs: { fileHandling: 'auto' } خود DuckDB-Wasm مسیرهای opfs:// داخل SQL رو خودکار رجیستر میکنه.
دو تا هشدار هم تو پست هست. اول اینکه OPFS استوریج مرورگره، نه یه تضمین محکم: مرورگر میتونه وقتی فضای دیسک کم میاد یا مدتها به اون سایت سر نزدی پاکش کنه، و کاربر هم از تنظیمات سایت میتونه پاکش کنه. نویسندهها میگن بهش مثل یه کش محلی سریع نگاه کن، نه تنها نسخهٔ دادهت. دوم اینکه نسخهای که npm به عنوان latest میده یعنی 1.33.1-dev57.0 فایلهای OPFS رو میسازه ولی هیچوقت توشون نمینویسه، پس چیزی ذخیره نمیشه؛ باید روی 1.32.0 پین کنی یا از تگ next استفاده کنی.
نکات کلیدی:
- برای ماندگار شدن دیتابیس، مسیر opfs://analytics.duckdb رو به db.open() بده
- نسخهٔ latest روی npm یعنی 1.33.1-dev57.0 باگ داره و چیزی ذخیره نمیکنه؛ 1.32.0 یا تگ next رو نصب کن
- پیشفرض checkpoint_threshold برابر ۱۶ مگابایته و با SET checkpoint_threshold = '0KB' صفر میشه
- OPFS از مارس ۲۰۲۳ تو مرورگرهای مدرن هست، per-origin و سندباکسشده
- هر فایل همزمان فقط یه handle میتونه داشته باشه، پس قبل از باز کردنش با کانکشن دیگه db.dropFile() بزن




