1

フリーとして設定されている SQLite データベースから行を選択し、その行を使用済みとしてマークする必要があります。選択と更新がアトミック操作であり、2 人のユーザーが同じ行を空きとして返すリスクがないことが重要です。

残念ながら、Laravel は を呼び出すときにトランザクション タイプを選択できないようDB::transactionですDB::statement

また、SQLite は変数をサポートしていないため、select と update の間に主キーを保存することはできません。そのため、これを SQLite データベースから実行できるかどうかはわかりません。

Laravel と SQLite を使用して行うことは可能ですか?

そうでない場合は、次の空き ID を SQLite データベースに関連する MySQL テーブルに格納し、代わりにその行でロックを使用する必要があります。MySQL で行ごとにロックするための大きな構文の違いはありますか? (テーブル全体を誤ってロックする余裕はありません)

私はこれに似た構文を見ています:(もちろんSQLiteは変数をサポートしていません)

BEGIN EXCLUSIVE TRANSACTION
  SET @free = SELECT InternalID FROM main WHERE Called = 0 LIMIT 1;
  UPDATE main SET Called = 1 WHERE InternalID = @free;
  SELECT * FROM main LEFT JOIN lead ON main.InternalID = lead.InternalID WHERE main.InternalID = @free;
END TRANSACTION

誰かが「なぜ 2 つのデータベース システムを使用しているのですか!?!」と尋ねると思うからです。

SQLite データベースには、柔軟な数の列を必要とするデータが含まれています。このデータは、週に数日、数か月間使用され、その後アーカイブできます。これらの「ミニデータベース」はかなりたくさんある必要があります。このデータは、MySQL に効率的に保存できません (以前のシステムで交換しようとしたところ、非常に遅くなりました)。各 SQLite データベースの同時実行性は非常に低くなりますが、2 人のユーザーが同じ行を取得する可能性がまったくないことが重要です。これは古いシステムで数回発生しました。

4

1 に答える 1

2

テーブルをロックしようとしたり、トランザクションでそれを実行したりするのを忘れてしまいます。これにはより良いパターンがあります。

  • 一意のトークンを生成する
  • そのトークンを次に利用可能なレコードに割り当てます
  • トークンを取得した行を読み取り、処理します

そうすれば、ロックやトランザクションはまったく必要ありません (DB はトークンを 1 つの未使用レコードにのみ割り当てるため)。

擬似コード:

$token = time(); //Only you have very low concurrency. Otherwise use something more unique, like a GUID or an identity value from a tokens table.

EXEC SQL: "UPDATE mytable SET token = $token WHERE token IS NULL LIMIT 1"

EXEC SQL: "SELECT id FROM mytable WHERE token = $token"

process($id);
于 2013-06-19T16:15:12.493 に答える