web-dev-qa-db-ja.com

MySQLがストアドプロシージャでLOCK TABLESを禁止するのはなぜですか?

MySQLリファレンスマニュアルのいくつかのセクションを読みましたが、ストアドプロシージャでLOCK TABLESは使用できないと繰り返し述べていますが、その背後にある理由の説明はありません。

5
Jeff

tl; dr

(トランザクションの途中でストアドプロシージャを呼び出すなどして)意図しないコミットを発生させないようにするため、これらは禁止されています。

(現在は非推奨)MySQLメーリングリストからコピー:

以下は、私がそこに作成した投稿へのShawn Greenの answer であり、同じスレッドの別の投稿者への彼の reply です:

こんにちはジェフ、

2018年8月13日の午後12時5分、jeff @ strippedは次のように書いています。

こんにちは、リファレンスマニュアルのいくつかのページを読みましたが、ストアドプロシージャでLOCK TABLES(およびUNLOCK TABLES)が許可されていないと記載されている例をいくつか見ましたが、これまでのところ、 理由についての説明です。誰かが私を啓発してくれませんか?

ありがとう

通常、リストはこれよりも反応が速いです。これはかなり簡単な質問であり、バックストップとして介入する必要がある前に、誰かが通常それらを処理します。

ストアドプログラム内でLOCK TABLEコマンドを実行できない主な理由は次のとおりです: https://dev.mysql.com/doc/refman/5.7/en/lock-tables-and-transactions.html =

LOCK TABLESはトランザクションセーフではなく、テーブルをロックする前にアクティブなトランザクションを暗黙的にコミットします。

ストアドプログラムは、開始されたトランザクションの範囲で実行されます。これは、どの行のセットがルーチンに「見える」かを決定し、必要が生じた場合にコミットまたはロールバックできるものに境界を設定します。

(簡単な例)

* your session: START TRANSACTION
* your session: ...other data activity ...
* your session (INSERT ... )
   * causes an INSERT trigger to fire
     * which calls a stored procedure

そのストアドプロシージャまたはそのトリガーがLOCK TABLEコマンドを呼び出した場合、その瞬間まで作業していた既存のトランザクションを強制的にコミットします。後のステップでROLLBACKコマンドを発行する必要があったとしても、半分完了した作業は完全にコミットされます。

マルチステートメントトランザクションを使用していない場合でも、ユーザーコマンドのスコープ内で呼び出された、または実行されたストアドプログラムは、その小さなミニ(自動コミット)トランザクションの一部であることに注意してください。

それは役に立ちますか?

-
ショーングリーン
MySQLシニアプリンシパルテクニカルサポートエンジニア
Oracle USA、Inc.-ハードウェアとソフトウェア、連携するように設計されています。
オフィス:テネシー州ブラウントビル


こんにちはモーゲン、

2018年8月18日午後2時32分、モーゲンズメランダーは次のように書いています。

みんな、

昔から覚えていると思います。

ロックを要求して、安全であればOKを取得できます。

保留中のトランザクションがある場合、ターゲットテーブルで、NOが返されます。

しかし、再び。私は間違っている可能性があり、ショーンはこれに対する権威です。

ロックの要求は、既存のすべてのリーダーまたはライター(要求したロックのタイプに応じて)がロックするテーブルの使用を完了するまで待機していました。つまり、ロックしたいテーブルに対してアクティブなトランザクションは、要求が許可される前にコミットまたはロールバックする必要があったことを意味します。テーブルに対する新しいアクションは、LOCKリクエストの背後にキューイングされていました。 LOCKがこのような厳しいボトルネックになることを彼らが知らなかったので、これは複数のDBAを混乱させました。

これらの種類のテーブル全体のロックは、個々のストレージエンジンまたはトランザクション制御コードのブロッキング/ロックの調整より上に存在します。これらは、コードの「サーバー層」で管理されます。

この範囲の分離は、同じデータ管理プロセスでトランザクションテーブルと非トランザクションテーブルをブレンドすることが一般的に嫌われる理由の1つです。全トランザクション(InnoDB)かそうでないかのどちらかです。動作が予測しやすくなり、開発者がトランザクション制御コマンド(BEGIN/COMMIT/ROLLBACK/...)またはLOCKコマンドを自信を持って使用できるようになります。

あなたの
-
ショーングリーン
MySQLシニアプリンシパルテクニカルサポートエンジニア
Oracle USA、Inc.-統合クラウドアプリケーションおよびプラットフォームサービス
オフィス:テネシー州ブラウントビル

0
Jeff

「ここに理由」の記述も見つかりませんでしたが、以下のリンクにある項目を読むと、以下の組み合わせのようです。

  • 推奨されるベストプラクティス :SELECT ... FOR UPDATEを使用します
  • row-level-locking の設定がテーブルレベルのロックよりも優先されます
  • concurrency に関連して発行されたパフォーマンスと、行レベルのロックの細分性
  • mySQLストアドプロシージャフォーラムに表示される他の代替手段には、テーブルレベルのロックが本当に正当化されている場合、またはテーブルレベルのロックではなくトランザクションを使用している場合のストレージエンジンの切り替え(ただし、LOCK TABLESステートメントをSPに取得できない)が含まれます。これらの選挙はおそらく、元の質問に現れていない他の考慮事項に帰着します。
  • また、「任意のSQLステートメント」は許可されないことを宣言するストアドプロシージャに関するステートメントを見ました。 「任意のSQL」のリストを探していませんでした。

幸運を

2
Cary Reams