App Store で入手
学習法

Anki で2台目を使うと学習の記録が消えるのはなぜか——同期の設計で決まること

2台目の iPhone を買って、Anki なり別の暗記アプリなりを入れて、同期をオンにする。そこで片方の端末でやったぶんの学習記録が消える——珍しい話ではありません。

先に結論を書きます。多くの場合これは不具合ではなく、同期の設計どおりの動作です。 同期には「どちらかのデータで上書きする」やり方と「両方を突き合わせて合流させる」やり方があり、前者を選んでいる場合、後から同期した側の記録は設計上必ず消えます

そして厄介なのは、情報の種類によって正解が違うことです。「あとが勝つ」で扱ってよい情報と、足し合わせないと消える情報が同居しています。この記事では何がどう消えるのかを、暗記アプリの同期を実装した立場から説明します。Anki を例に挙げますが、原因は Anki 固有のものではありません——間隔反復で学習履歴を持つアプリに共通の問題です。このサイトは RepeCa の開発元が運営しています。

なぜ2台目を使い始めた瞬間に消えるのか

危ないのは、両方の端末に既にデータがある状態で初めて同期したときです。

片方が空なら問題は起きません。空の端末に流し込むだけだからです。しかし2台とも使い込んでいると、同じカードについて2つの異なる履歴がある状態になります。ここでどちらを採用するかを決めなければならず、その決め方が設計そのものです。

Anki の公式マニュアルも、この場面を特別扱いしています。

If you have different cards on both devices, more work is required to avoid losing data. (両方の端末に異なるカードがある場合、データを失わないためには追加の作業が必要です)

Anki Manual, Syncing(2026-08-26 確認)

「追加の作業が必要」と書かれている時点で、自動では守られないということです。

同期は何を「勝たせる」かを決めているだけ

同期の設計とは、突き詰めると「衝突したときに何を勝たせるか」の規則です。

もっとも単純なのは LWW(Last Write Wins・あとが勝つ) で、タイムスタンプが新しい方を採用します。実装が単純で、多くの場面で妥当です。

上書き型(あとが勝つ)端末A累計 8 回端末B累計 12 回新しい方結果累計 8 回← 12回ぶんが消える合流型(増分を足す)端末A +8端末B +12両方結果累計 20 回← 消えない

問題は、暗記アプリのデータが1種類ではないことです。 RepeCa では3つに分けて規則を変えています(実装確認: sync/merge.ts。2026-08-26 時点)。

情報の種類勝たせ方
カードの内容表・裏・所属フォルダ・タグあとで編集した方updatedAt の LWW)
復習スケジュール現在のレベル・次に出る日あとで採点した方
累計の記録生涯の正答数・誤答数🔴 両端末の増分を足す

3つ目だけ扱いが違います。理由は次の節です。なお、ここでいう「レベル」と「次に出る日」が何を指すのかは間隔反復(SRS)とはにまとめてあります。

累計の数字を「あとが勝つ」で扱うと何が起きるか

消えます。しかも気づきにくい形で消えます。

端末Aで8回、端末Bで12回そのカードに答えたとします。「あとが勝つ」で処理すると、結果は 8 か 12 のどちらかになります。本当は20回答えているのに、記録上は片方だけが残ります。

カードの表裏なら「あとが勝つ」で構いません。最新の1つが正しいからです。しかし累計の数字は履歴の積み上げなので、片方を捨てると積み上げた事実そのものが消えます。

RepeCa は端末ごとに「前回の同期からどれだけ増えたか」を覚えていて、その増分を足し合わせます。実装上は server + max(0, ローカルの値 - 前回同期時の値) という形で、二重計上も欠落もせずに揃います。

⚠️ この違いは、使っていて気づきません。 正答率の分母が減っても「そんなものか」と思うだけで、エラーも警告も出ないからです。復習スケジュールは正常に動き続けるので、不具合として認識されません。統計を見返したときに数字が合わない、という形でようやく気づきます。

消したはずのカードが復活するのはなぜか

削除を「レコードが無い状態」として同期すると、必ず復活します。

端末Aでカードを消したとします。同期のときに端末Aは「そのカードを持っていない」状態です。一方で端末Bはまだ持っています。ここで「持っている方を正とする」と、削除が「まだ受け取っていないだけ」と区別できません。結果、消したカードが戻ってきます。

解決策は、削除を消えた状態ではなく「消したという記録」として送ることです。RepeCa では削除された印(deletedAt)を持つレコードを送り合い、内容と同じ LWW の規則で伝播させます。削除も1つの編集として扱う、という考え方です。

同じ名前のタグが増えるのはなぜか

2台で同じ名前のタグを別々に作ると、内部の識別子が違うので別物として両方残ります。

利用者から見れば同じ「英単語」というタグですが、システムから見れば別のレコードです。同期のたびに増えていき、タグ一覧に同じ名前が並びます。

RepeCa は受信時に同じ名前のタグを1つへ畳みます(実装確認: sync/apply.tsdedupeTagName)。どちらを残すかは識別子の小さい方に固定していて、どの端末から見ても同じ結果になるようにしています。勝者を「先に届いた方」にすると端末ごとに違う結果になり、収束しません。

初回に「どちらかを選ばせない」ようにする

両方に既にデータがある初回同期こそ、いちばん壊れやすい場面です。

RepeCa は同期をオンにしたとき、クラウドの全件を取り込んでから、手元の全件を送り出します(実装確認: sync/engine.tsbootstrapSync)。順序が逆だと、取り込む前に上書きしてしまいます。この2段階を踏むので、利用者に「アップロードとダウンロードのどちらか」を選ばせる場面がありません

同じ id のカードが両方にあれば上の3つの規則でマージされ、片方にしかないカードはそのまま残ります。結果は両者の合流になります。

受信したレコード1件を適用する処理は1か所に集約してあります。通常の受信と、衝突が起きたときの解決が同じコードを通るようにするためです。2か所に分けて書くと、片方だけ直したときにドリフトが起きます。

それでも RepeCa の同期が既定オフなのはなぜか

ここは正直に書きます。設計は上のとおりですが、2台同時に使ったときの挙動を実機で十分に検証できていません。

RepeCa の iCloud 同期は既定でオフで、使うには設定から手動で有効にする必要があります。この一手間を意図的に残しているのは、検証体制がまだ限定的だからです(実装のコメントにもその理由を残してあります)。

設計上の規則を決めてあることと、2台で動かして確かめたことは別です。 前者は説明できますが、後者はまだ胸を張れる段階にありません。検証が済んだら、この記事にも実測を追記します。

同期そのものの仕様はiCloud 同期に、有効にする手順はiCloud 同期を有効にするにまとめてあります。

使う側にできること

道具を選ぶ・使う立場からは、次の3点が効きます。

  1. 2台目を使い始める前に、片方で同期をオンにして送り出しておく——両方に育ったデータがある状態を作らないのが、いちばん確実です
  2. 書き出し(エクスポート)ができる道具を選ぶ——同期の設計は外から確かめられませんが、書き出せれば最悪の場合に自力で戻せます
  3. 累計の数字を時々見ておく——正答率の分母が不自然に減っていたら、上書き型の同期が働いた可能性があります

意図して学習の記録を戻したい場合は別の話で、そちらは学習履歴のリセットにまとめました。意図せず消えるのが本記事、意図して戻すのがあちらです。

まとめ


この記事について

このサイトは、暗記アプリ RepeCa の開発元が運営しています。本文の設計判断(3種類のマージ規則・削除の伝播・同名タグの畳み込み・初回同期の順序)は、実装のときに決めた内容とその理由をそのまま書いたもので、2026-08-26 にコードを読み直して確認しています。

RepeCa の同期は既定オフで、2台同時に使ったときの挙動は実機で十分に検証できていません。 「うちは解決済み」という記事ではなく、「こういう分かれ道があり、私たちはこう選んだ」という記事として読んでください。

← 暗記のコツの一覧へ