見出し画像

TWSNMPのバックアップ機能 その後

復刻版TWSNMPのデータベースのバックアップ機能をテストしていると、メモリ不足でMacが自動的のシャットダウンしていました。ちょっと甘く見て手抜きした部分が原因でした。その教訓を書いておきます。

メモリ不足でMacがシャットダウン!

復刻版のTWSNNPは、しつこいですが

というデータベースを使っています。バックアップの処理に、

のコマンドを応用していますが、その中の

	if err := cmd.walk(src, func(keys [][]byte, k, v []byte, seq uint64) error {
		// On each key/value, check if we have exceeded tx size.
		sz := int64(len(k) + len(v))
		if size+sz > cmd.TxMaxSize && cmd.TxMaxSize != 0 {
			// Commit previous transaction.
			if err := tx.Commit(); err != nil {
				return err
			}

			// Start new transaction.
			tx, err = dst.Begin(true)
			if err != nil {
				return err
			}
			size = 0
		}
		size += sz

の一定サイズでトランザクションをコミットする部分を手抜きして省略しました。そのプログラムのテストで36GBのデータベースをバックアップしていたら、いつのまにかメモリ不足でMacがシャットダウンしていました。最初、バックアップを実施してもバックアップファイルのサイズが16KBで変わらずオカシイと思っていましたが、トランザクションをコミットしないとディスクに保存せずメモリに保存してメモリの使用量が増えていくことがわかりました。
シンプルにできたと喜んでいたのが失敗でした。そんなに甘くない!
という訳でこの部分は、参考にしたプログラムと同じようにデータ量を64KB単位でコミットするよう修正して解決しました。
ライブラリの開発者のサンプルプログラムには、大事なことが書いてあると再認識しました。ちゃんと理解しようと思いました。

いつまでも止まらないバックアップ!

トランザクションの問題の他にもう一つ問題がありました。
バックアップ処理の途中でTWSNMPを終了しても上手く止まらないというおものです。

func (cmd *CompactCommand) walk(db *bolt.DB, walkFn walkFunc) error {
	return db.View(func(tx *bolt.Tx) error {
		return tx.ForEach(func(name []byte, b *bolt.Bucket) error {
			return cmd.walkBucket(b, nil, name, nil, b.Sequence(), walkFn)
		})
	})
}

のForEachで処理をしなくても成功(エラーなし)を返したら、コピー元のデータベースに登録されているデータ全部に対してなにもしない処理を繰り返すような無駄なことになっていました。ドキュメントのForEachの説明

にちゃんと書いてありました。

ForEach executes a function for each bucket in the root. If the provided function returns an error then the iteration is stopped and the error is returned to the caller.

終了した時にエラーを返すようにしたら、ちゃんと止まるようになりました。これは、ちょっと知恵を得たので、ちょっと満足!
でも、「ドキュメントはちゃんと読もう」と思いました。

結局どうなったか?

この土日に悪戦苦闘して、何とか、

で考えたことは作ることができました。バックアップでデータベースのサイズが小さくなることも確認できました。36GBのデータベースをバックアップすると16GBになりました。ただし、2時間かかりました。1日1回なら360GBぐらいが限界かもしれません。

画像1

1回だけバックアップすることや、夜中の3時に毎日バックアップすることができます。ちゃんと、今朝の3時に実施してました。

画像2

バックアップは楽になった!

今回作ったバックアップ機能は、ファイル名を固定して1日1回出力するようになっています。昔から定番のバックアップ方法ではファイル名や保存先のフォルダ名に日付を含めたたりして別ファイルとして追加していくのが常識でした。3日前のファイルがリストがあるので直感的にそのほうが安全なように思えます。
でも、その方法にしなかったのは、一番は楽したいからでもありますが、自分で作らなくても最近のOSのバックアップは、勝手に、そうしてくれるからです。Macだとタイムマシーンです。最近、Windows 10のバックアップを設定したらタイムマシーンと似たような機能が追加されていました。
複雑な処理を自分で作らなくても、3日前のバックアップファイルは手に入るよい時代になったと思います。

今日の猫

今朝 猫は、かみさんにベランダに出してもらって、大好きな雨を舐めていました。私が起きると濡れた体で「抱っこしろ!」と私のパジャマで体を拭いていました。1時間毎にベランダにでて濡れて帰ってきます。

つづく

開発のための諸経費(機材、Appleの開発者、サーバー運用)に利用します。 ソフトウェアのマニュアルをnoteの記事で提供しています。 サポートによりnoteの運営にも貢献できるのでよろしくお願います。