資料安全Data safety
正常關服
同步保存全部餘額,且在關閉連線池之前完成。資料庫寫入失敗時:
- 重試 3 次,間隔 400ms
- 仍失敗則寫出
balances-emergency-<時間戳>.yml - Console 顯示
Saved N player balances before shutdown.
Balances could NOT be saved…,請到插件資料夾找緊急檔。
重開後自動補寫
啟動時掃描緊急檔,依時間戳由舊到新套用(較新的覆寫較舊的),
寫回資料庫後改名為 .recovered,確保不會重複套用。
若寫回仍失敗則保留檔案,下次啟動再試。
由 storage.recover_emergency_dumps 控制,預設開啟。
false ——
A 伺服器的舊 dump 可能覆寫 B 伺服器寫入的較新數值。
關閉後檔案照樣產生,改由人工確認後復原。
當機 / OOM / kill -9
onDisable() 不會執行,會遺失最後一次 flush 之後的交易。
預設設定下損失視窗約 1 秒。
正常 /stop、面板關閉、docker stop(SIGTERM)都會觸發完整的關服存檔流程,
只有 SIGKILL 與 OOM-killer 會跳過 —— 那時沒有任何程式碼能執行。
金額安全
- 轉帳時若入帳失敗,會退款給付款方,金錢不會憑空消失
- 存款溢位時飽和到最大值,而不是把帳戶歸零
- 所有餘額變更都是原子操作,並行呼叫不會遺失更新
Clean shutdown
Every balance is written synchronously, before the connection pool closes. If the database write fails:
- It is retried 3 times, 400 ms apart
- If it still fails, balances go to
balances-emergency-<timestamp>.yml - The console reports
Saved N player balances before shutdown.
Balances could NOT be saved…, look for an
emergency dump in the plugin folder.
Automatic recovery on the next start
Startup scans for emergency dumps, applies them oldest to newest so a later dump wins, writes
them back to the database, then renames each file to .recovered so it can never be
applied twice. If the write-back still fails the files are kept for the following start.
Controlled by storage.recover_emergency_dumps, enabled by default.
false if several servers share one database — a stale dump from one
server could overwrite newer values written by another. Dumps are still produced; recovery just
becomes a manual decision.
Crash, OOM, kill -9
onDisable() does not run, so transactions since the last flush are lost. With the
defaults that window is about one second.
A normal /stop, a panel shutdown and docker stop (SIGTERM) all run the
full shutdown save. Only SIGKILL and the OOM killer skip it — at which point no code can run at
all.
Money safety
- If the credit leg of a transfer fails, the sender is refunded; money is never destroyed
- A deposit that would overflow saturates instead of resetting the account to zero
- Every balance mutation is atomic, so concurrent callers cannot lose updates