オブジェクトストアのロック
2007/03/30 (Fri) 22:07:46 JST
ロック可能なクラス
?オブジェクトストア、 EOObjectStore のサブクラスでは NSLocking インターフェースが実装されており、 lock()
, unlock()
のメソッドを実装しています。具体的には次のクラスがロック可能なオブジェクトストアとなります。
オブジェクトストアをロックするとどうなるのか
オブジェクトストアのロックは ?NSRecursiveLock で、実行中のスレッドにオブジェクトストアの操作権限を与えるだけです (スレッドのロックを参照) 。オブジェクトストアをロックしたからといって、データベースに対してテーブルロックや行ロックを行うことはありません。
ポイントは1つの EOObjectStoreCoordinator がアプリケーションインスタンス内で共有されることです。1つしかない EOObjectStoreCoordinator がロックされれば、当然他スレッドから EOObjectStoreCoordinator を使う操作、フェッチや保存などのデータベースアクセスは行えなくなります。結果として確実なデータベース操作が保証されることになります (これがEOFの言うスレッドセーフです) 。
ただし、これはあくまで同一アプリケーションインスタンス内での話です。あるインスタンスで EOObjectStoreCoordinator がロックされていようが、他インスタンスでは何も問題なく EOObjectStoreCoordinator を通してデータベースにアクセスすることができます。
EOEditingContextのロック
EOEditingContext は EOObjectStoreCoordinator 、 EOObjectStoreCoordinator は EODatabaseContext と、各オブジェクトストアは連携しています。EOObjectStoreCoordinator と EODatabaseContext は自動的にロックされますが、そのタイミングは EOEditingContext のロック時ではありません。EOEditingContext がデータベースアクセスを必要とする操作 (フェッチ、保存など) を行うときに EOObjectStoreCoordinator 以下をロックします。セッションが持つデフォルトの EOEditingContext は Request-Response ループの開始時にロックされますが、この時点ではデータベース操作まではロックされていません。
オブジェクトグラフの同期
saveChanges()
を実行すると、他の EOEditingContext に編集中のオブジェクトがあるかないかに関わらず、すべてのオブジェクトグラフがデータベースの最新の内容と同期されます。編集中のオブジェクトはフォールトに戻され、最新の内容が編集中の内容にマージされます(ただしフェッチ時刻によっては何も操作されず、そのままの状態が維持されます) 。
つまるところオブジェクトストアのロックの目的とは、アプリケーションインスタンス内のデータベースレコードのキャッシュを常に最新のものにしておくということです。その結果として、オブジェクトグラフとデータベースの内容が同期されます。オブジェクトグラフ間の編集中のオブジェクトを検出し、競合と判断して例外を発生させることではありません。
ここで編集中のオブジェクトを保存した場合、気分的には他スレッドが保存処理を行う前から編集しているのだから競合とみなしてエラーになって欲しいという希望もあるかと思いますが、エラーにはなりません。なぜかというと、オブジェクトグラフが同期された時点で、編集中のオブジェクトの未編集の値は最新の内容にマージされてしまうからです。これについてはオプティミスティックロックも参照してください。
オブジェクトの編集合戦
EOEditingContext をロックしたからと言ってデータベース操作までロックされないということは、例えロック中でもオブジェクトグラフが同期される可能性があるということです。同期後に、直前に更新したレコードに対応する編集中のオブジェクトを保存しても例外が発生しないため、複数のスレッド間で同一のレコードに対応するオブジェクトを操作していると内容が壊れる可能性があります。
この編集合戦を防ぐには次の方法が考えられます。
- 編集開始時の状態を保存しておき、保存直前に比較する
- フェッチ時刻を調整して同期されないようにしておく
- デリゲートを使うなどして、編集の競合を検出するためのロックを実装する
- 複数のスレッドで同一のレコードに対応するオブジェクトを操作させない
実際には同一のレコードを複数のユーザが同時に編集するような状況はあまりないと思うので、「気にしない」というのもありかと思います。
Inverse Pages: ロックについて