したがって、MySQL 5.5のドキュメントを読んだり、同僚と行ったいくつかの実験から、次のことが当てはまることがわかります。
SELECT
ステートメント(FOR UPDATE
またはLOCK IN SHARE MODE
を使用しないもの)は、SELECT
ステートメントが読み取るテーブルの行ロックを取得しません。これは、すべてのトランザクション分離レベルに当てはまります。REPEATABLE READ
以上の場合、INSERT ... SELECT
またはCREATE TABLE AS SELECT
ステートメントは、が読み取るテーブルに行ロックを設定しますから。出典:
私がこれを正しく理解している場合(そして、理解していない場合は修正します)、この違いに戸惑います。トランザクション分離レベルが同じである場合に、テーブルの読み取りでロック行が必要になるケースがあるのはなぜですか?その理由を知りたいのですが。
MySQLドキュメント から
読み取りのタイプは、INSERT INTO ... SELECT、UPDATE ...(SELECT)、およびCREATE TABLE ... SELECTなどのFOR UPDATEまたはLOCK IN SHARE MODEを指定しない句のselectによって異なります。
デフォルトでは、InnoDBはより強力なロックを使用し、SELECT部分はREAD COMMITTEDのように動作します。同じトランザクション内でも、一貫した読み取りごとに、独自の新しいスナップショットを設定して読み取ります。
このような場合に一貫した読み取りを使用するには、innodb_locks_unsafe_for_binlogオプションを有効にし、トランザクションの分離レベルをREAD UNCOMMITTED、READ COMMITTED、またはREPEATABLE READ(つまり、SERIALIZABLE以外のもの)に設定します。この場合、選択したテーブルから読み取られた行にロックは設定されません。
明らかに、読み取りを行うだけの場合は、より強力なロックは必要ありません。 INSERT ... SELECT
またはCREATE TABLE ... SELECT
を使用してテーブルにデータをコピーする画像。 SELECT
は、テーブルをロードするための凍結されたスナップショットである必要があります。移動ターゲットの場合、トランザクション内でトランザクションが必要になります。 transaction within a transaction
の動作が必要な場合は、 [〜#〜] savepoint [〜#〜] を使用してスクリプトを作成する必要があります。それ以外の場合、より強力なロックにより、アトミックINSERTの一貫したSELECTが可能になります。
単純なSELECT
を実行すると、DBセッションは、他のトランザクションを信頼して、データのビューで smoke-and-mirrors を再生できなくなります。その信頼に違反する必要がある場合、データが実際に変化しているときにデータが安定していると考えてSELECTのみを実行しているDBセッションを欺くのではなく、作業を実行できるすべての行を丁寧にロックします。
どの 分離レベル を選択しても、単純なSELECTが維持されるほど細かいものはありません。 SELECT ... FOR UPDATE
およびSELECT ... FROM ... LOCK IN SHARE MODE
が発明されたのはそのためです。そのため、ポライトレスがオプションでない場合は、そのように細かくすることができます。
私はこれについて前に書きました: selectステートメントをブロックさせるにはどうすればよいですか?