How to Recover a Tokyo Cabinet Database
Recently Mark Callaghan had asked me whether BlitzDB is crash safe since he was aware that Tokyo Cabinet isn’t crash safe (unless used with transactions). For Tokyo Cabinet and Tyrant’s defense, I should mention that this is intentional. The idea is to reduce durability in return for higher throughput. The author’s philosophy is that data availability should be secured by replication. This makes sense since the design of TC and TT are influenced by mixi’s high traffic (we need single instances to handle over 10k requests per sec).
So with that said, let’s move on to the main topic. The honest answer is that BlitzDB is not crash safe either (transaction support is still a long way to go). If the admin is lucky, she would be able to repair the table(s) using the REPAIR TABLE syntax. BlitzDB’s crash safety strategy is the same as Tokyo Tyrant – You should use replication. The question is, how do you repair a broken Tokyo Cabinet file?
The answer is pretty simple and it’s documented in the Japanese TC documentation. Unfortunately it’s not not present in the English documentation. So allow me to go through it with demo code in this post. There are two ways to attempt to recover a Tokyo Cabinet database:
- By using the Tokyo Cabinet API.
- By using Tokyo Cabinet’s command line tool.
Let’s first go through how to confirm that your database is broken. I’ve also covered how to comprehend the errors.
How to confirm that your Database is broken
Simply use the command line tools installed with Tokyo Cabinet. Look at the “additional flags” line on the output of “tchmgr inform” or “tcbmgr inform” depending on your database type. If it says, “fetal” then your file is really broken. If it says “open”, it means that your application died or exited without closing the database. A file in the “open” state is still usable but your most recent records are most likely unavailable. This is because TC connects the hash chain after it has confirmed that a write operation was successful. If your application died before the record is chained, then it’s not accessible in the database.
Furthermore, the records that weren’t sync’d by the kernel won’t be present on power failure. If the disaster was a process failure, then the written data will hopefully be in the kernel’s write buffer so you won’t lose that data. For pedantic people, TC provides a way to sync the database from your application. Whether to call this function (and how often) is up to your application’s policy.
Using the Tokyo Cabinet API
(1) Open the database file without the lock option. Meaning, supply HDBONOLCK or BDBONOLCK to the open function of the appropriate database type (TCHDB or TCBDB).
/* This is for TCHDB */ TCHDB *hdb = tchdbnew(); if (!tchdbopen(hdb, "/path/to/broken_file", HDBONOLCK | HDBOWRITER)) { /* Failed to open. Do the appropriate thing. */ } /* This is for TCBDB */ TCBDB *btree = tcbdbnew(); if (!tcbdbopen(btree, "/path/to/broken_file", BDBONOLCK | BDBOWRITER)) { /* Failed to open. Do the appropriate thing. */ }
(2) Run tchdboptmize() or tcbdboptimize() depending on the database type. You might wonder what you should give as the parameter for the optimize function. Conveniently, TC stores the tuning parameters of the database when you first opened it so you can just provide -1 as an argument _but_ the final one. This is because the final argument is an unsigned integer (uint8_t). What you want to provide instead is UINT8_MAX for this.
/* This if for TCHDB */ if (!tchdboptimize(hdb, -1, -1, -1, UINT8_MAX)) { /* We're out of luck. This hash database can't be rescued. */ } /* This if for TCBDB */ if (!tcbdboptimize(btree, -1, -1, -1, -1, -1, UINT8_MAX)) { /* We're out of luck. This b+tree database can't be rescued. */ }
If you’re lucky, the above would repair the database that is associated with TC’s database object.
Using TC’s command line tool
This approach is more towards database admins since I’m sure the last thing they want to do is write their own program to get their work done. Lazyness is good.
TC provides a utility program called tchmgr (for a hash database) and tcbmgr (for a b+tree database) which allows you to run optimize on a database file. So if you wanted to repair a TC hash database, you would do the following:
$ tchmgr optimize -nl /path/to/broken_file
and the following for the B+Tree Database:
$ tcbmgr optimize -nl /path/to/broken_file
For those that are interested, the “-nl” option means “No Lock” which is required to repair a database file.
Well, I guess this sums up this blog post. I hope this post will help you administrate Tokyo Tyrant and/or your Tokyo Cabinet based application!

Why do the slides for the successor to Tokyo Cabinet (http://1978th.net/kyotocabinet/) continue to suggest that this provides ACID when it isn’t crash safe?
OK, so Tokyo Cabinet is not crash safe. And yet, at
http://1978th.net/tokyocabinet/spex-en.html#features
we see the statement
“improves robustness : database file is not corrupted even under catastrophic situation”
What does that mean?
@Mark Callaghan It is crash safe if you tell it to be so. Specifically when you open the database.
@Mike Spreitzer So, despite the common belief, if you use TC’s Transaction API then it is crash safe. Though you must remember that this obviously reduces throughput.
Is possible to create databases with separate INDEX files and DATA files..?
TC binds Value and Index inside only one file, but how to separate them
in different files, i.e. “file.tcb – file.idx”
meaning: file.tcb containing data values or records only
file.idx containing indexes pointing to the values or records in file.tcb..
With this, recovering one broken database could be very easy..
@Marc Cunning That’s not possible since you’re asking Tokyo Cabinet to have a different (or split) storage format. Although, it’s possible to do it on the layer above which I do for one of my projects (B+Tree for the Index).