スクリプトによる疑似的な悲観的排他制御の実装方法
まず、「悲観的排他制御」とは「他の人が変更するかもしれないから、先にロックして安全に編集する」という方式です。
編集開始時にレコードをロックし、保存が完了するまで他のユーザーは編集できなくなります。
主なメリットは以下のとおりです。
・データの不整合をほぼ確実に防げる(更新衝突が発生しない)
・ユーザーにとって直感的(「誰かが編集中で触れない」という分かりやすい状態で混乱しない)
・重要業務(在庫管理、金融処理など)で信頼性が高い(同時編集が許されない業務に最適)
一方で、次のようなデメリットもあります。
・ロック中は他のユーザーが編集できない(作業が長引くと待ち時間が発生し、効率が低下)
・ロックが解除されないリスク(永続ロック=デッドロック状態が起きる可能性)
・複数人で同じデータを頻繁に扱うシステムには不向き(ロック待ちが連続して発生し、ストレスが大きい)
悲観的排他制御を実装する際には、これらのメリットとデメリットを十分に考慮したうえで採用を判断する必要があります。
実際にロック機能を再現する一例をご紹介します。
今回ご紹介するのは、クライアントスクリプトによるロック機能です。
■全体的な仕組み
①レコード内に編集者名を保持する項目を用意する
②その項目が空の場合、編集画面を開いたログインユーザー名を取得し、項目に設定した上でレコードを自動更新する
③編集画面を開いたログインユーザー名と②で登録されたユーザー名を比較する
➡一致する場合:「更新」ボタンを有効化
➡一致しない場合:「更新」ボタンを無効化
④一致したユーザーが「更新」ボタンをクリックすると、編集者名を空にしてレコードを更新する
■事前準備
・レコード内に編集者名を保持する分類A(ClassA)を有効化し、「読取専用」に設定して自由に編集できないようにします。
・「テーブルの管理」画面の「スクリプト」タブで、以下二つのスクリプトを出力先「編集」にチェックを入れて設定します。
✅レコード編集画面表示時の処理スクリプト
$p.events.on_editor_load = function () {
// URLに「reloaded=1」があれば実行しない(無限ループ防止)
if (location.search.includes("reloaded=1")) {
return;
}
var classAValue = $p.getValue('ClassA'); // ClassAの値を変数に格納
var loginUser = $p.userName(); // ログインユーザー名を変数に格納
var $updateBtn = $("#UpdateCommand"); // 「更新」ボタンを変数に格納
// ClassA が空欄の場合 → ログインユーザー名を自動入力して$p.apiUpdateで更新
if (!classAValue) {
$p.apiUpdate({
id: $p.id(),
data: {
ApiVersion: 1.1,
ClassHash: {
ClassA: loginUser
}
}
}).then(function () {
location.href = location.pathname + "?reloaded=1"; // 無限ループ防止用パラメーターを付与
});
return;
}
// ClassA が空でなく、ログインユーザーと不一致の場合
if (classAValue !== loginUser) {
// ① 編集画面表示時にアラート表示
alert("ClassA がログインユーザーと一致しないため、更新できません。");
// ② 更新ボタンのクリックイベントを無効化
$updateBtn.off("click"); // jQuery が付けたイベントを削除
$updateBtn.removeAttr("onclick"); // HTML 属性のイベントも削除
// ③ 更新ボタンをグレーアウト
$updateBtn.prop("disabled", true);
$updateBtn.css({
"opacity": "0.5",
"cursor": "not-allowed"
});
return;
}
// ClassA の値がログインユーザーと一致 → $p.apiUpdateで自動更新
$p.apiUpdate({
id: $p.id(),
data: {
ApiVersion: 1.1,
ClassHash: {
ClassA: loginUser
}
}
}).then(function () {
location.href = location.pathname + "?reloaded=1"; // 無限ループ防止用パラメーターを付与
});
}✅レコード更新時の処理スクリプト
$p.events.after_set_Update = function (args) {
// 表示されている ClassA の文字列(Results_ClassA)を削除
$('#Results_ClassA').text('');
// APIでClassAの値を空に更新
$p.apiUpdate({
id: $p.id(),
data: {
ApiVersion: 1.1,
ClassHash: {
ClassA: ''
}
}
});
}上記の設定を行うと、画面での動作は次のようになります。
※以下はログインユーザー名が「テスト次郎」の場合の例です。
サイト内には2件のレコードが登録されています。


①編集者名が空のレコードを開いた場合
編集者名にログインユーザー名が登録・更新され、ブラウザが自動リロードされます。
※この自動リロードが完了する前にレコードを更新すると、競合が発生して更新できなくなりますのでご注意ください。
その後、「更新」ボタンをクリックしてレコードを更新すると、編集者名がクリアされ、ログインユーザー以外のユーザーもこのレコードを編集できるようになります。


なお、レコード編集画面で「更新」ボタンによる更新を行わずに一覧画面へ戻ると、編集者名にログインユーザー名が残ったままの状態となり、レコードはロックされたままになります。


②編集者名に別のユーザー名が登録されているレコードを開いた場合
まずアラートが表示されます。


アラートを閉じて編集画面を開いても、編集者名は更新されず、「更新」ボタンも非活性化された状態となります。


今回ご紹介した方法では、編集者名のクリアを「更新」ボタンクリックのタイミングで実装していますが、運用に合わせてさまざまなカスタマイズも可能です。
例えば
・編集者名をクリアする専用ボタンを追加し、ユーザーが任意のタイミングでロック解除できるようにする
・編集者名を保持したまま更新する「一時保存」ボタンを追加し、編集中の状態を維持したまま内容だけ保存できるようにする
など
このように、基本の仕組みをベースに業務要件や利用シーンに合わせて拡張することで、より柔軟で実用的な排他制御を実現できます。
まとめ
今回ご紹介したスクリプトによる疑似的な悲観的排他制御は、プリザンター標準の楽観的排他制御では対応しきれない「更新競合を避けたい」「絶対に衝突してはいけない業務を扱いたい」といった場面で有効に機能します。
もちろん、悲観的排他制御には「同時編集が制限される」「ロック解除忘れのリスクがある」といったデメリットも存在します。
そのため、すべてのケースで万能というわけではなく、業務の性質やユーザー数に応じて使い分けることが重要です。
プリザンターは柔軟に拡張できるプラットフォームですので、標準仕様のメリットを活かしつつ、必要に応じてスクリプトで補うことで、より安心して業務に活用できる環境を整えることができます。
本記事の内容が、更新競合に悩む方や重要データを扱う業務での運用改善に役立てば幸いです。
弊社では、プリザンター導入・活用に関して以下のサービスをご提供しています。
・年間サポート
・各種書籍
・帳票出力(Excel/PDF)支援パック
プリザンターの導入から開発・運用をあらゆる角度から全力サポートいたします。
ぜひお気軽にご相談ください!
☆☆☆
サービスの説明などをご希望の方は【 問い合わせフォーム 】よりお気軽にお問い合わせください。
☆☆☆

MAIL


楽観的排他制御のメリットと限界
こんにちは、シーイーシーカスタマサービスの新村です。
プリザンターを利用していると、こんな経験はないでしょうか。
複数のユーザーが同じレコードを同時に編集し、保存しようとしたとき
――先に保存した人の内容だけが反映され、後から保存した人にはエラーが表示されてしまう。
結局、再度レコードを開き直して編集し直さなければならず、業務の流れが止まってしまいます。
これはプリザンターが採用している楽観的排他制御による仕様です。
「衝突はめったに起きないだろうから、編集は自由に行い、保存時に確認する」という考え方に基づいた仕組みであり、確かに以下のようなメリットがあります。
・複数ユーザーが同時に作業できる(編集画面を開いたままでもロックされない)
・ロック処理が不要でシステムが軽い(サーバー負荷が小さく、デッドロックも発生しない)
・Webシステムとの相性が良い(複数タブで編集しても問題が起きにくい)
しかし、現場で使うと次のような課題が浮かび上がります。
・保存時に更新競合エラーが発生する
・衝突後の再編集が手間になり、作業効率が落ちる
・在庫管理や金融記帳、契約情報など「絶対に衝突してはいけない」業務では不向き
つまり、楽観的排他制御は便利である一方、「衝突が許されない場面」では大きなリスクになるのです。
では、この問題をどう解決すればよいのでしょうか。
本記事では、プリザンターにおいてスクリプトを活用し、疑似的に悲観的排他制御を実現する方法をご紹介します。