記事ディレクトリ
Lock は、コンピュータが複数のスレッドを調整して同じ共有リソースにアクセスするためのメカニズムであり、主に同時実行セキュリティの問題を解決するために使用されます。複数のスレッドが同じ共有リソースにアクセスする。
ロックの分類
(1) パフォーマンスの観点から、楽観的ロックと悲観的ロックに分けられます MySQL が採用しているのは、バージョン番号管理、(2)ではJVM CAS
を使用 データベース操作の種類はリードロック(共有ロック)、ライトロック(排他ロック)に分かれます。 【リードロック、ライトロックは共に悲観ロック】
読み取りロック (共有ロック): 同じ行レコードに対して複数の読み取り操作を同時に実行できますが、トランザクションは実行できません
(1) 読み取りロック、書き込みロック ロックはすべて行レベルのロックです。つまり、トランザクション 1 は製品 A の書き込みロックを取得し、トランザクション 2 は製品 B の書き込みロックを取得し、相互にブロックしません。 (2) SQL ステートメントで行ロックが使用されている場合、SQL がインデックスを使用せずにテーブル全体のスキャンを使用する場合、行レベルのロックはテーブル ロックになります。
(3) ロックはコミットまたはロールバックが実行されたときにのみ解放され、すべてのロックが同時に解放されます。 (4) Innodb エンジンが通常の変更および削除 SQL ステートメントを実行すると、変更および削除された行に行ロックが追加されます。
共有ロック (読み取りロック、読み取りと書き込みの相互排他、読み取りと読み取りは相互に影響しません)
トランザクション A は、共有ロックを使用して特定の (トランザクション B がこれらのレコードを読み取ることができる場合、共有ロックの追加を続行できますが、これらのレコードを変更することはできません (トランザクション C がこれらのデータを変更または削除すると、ロック待機がタイムアウトになるかトランザクションが終了するまでブロック状態になります) A コミット)
共有ロックの使用方法と共有ロックの解放方法
# 加锁SELECT ... LOCK IN SHARE MODE# 释放锁commit;rollback;
例: 製品在庫に対する同時操作
select ... for update は、読み取り行レコードに排他ロックを追加し、排他ロックを取得したトランザクションのみが行レコードを変更できるようにし、他のトランザクションが行レコードを変更できないようにします。通常と同じように行 update ステートメントは実行時に行ロックを追加します。
排他ロックの使用方法
# 加排他锁select ... for update //排他锁 # 释放锁commit;rollback;
(1) トランザクションごとに 1 回排他ロックを取得すると、他のトランザクションは排他ロックを取得できなくなります。 複数のトランザクションで、同じデータ行に共有ロックを追加できます。
(2) 他のトランザクションもその行に共有ロックまたは排他ロックを追加する可能性があるため、指定された行に共有ロックを追加するトランザクションは、必ずしもその行のデータを変更するとは限りません。排他ロックを追加するトランザクション指定された行に追加すると、排他ロックを使用して行データを変更できます。
#テーブル ロック
テーブル レベルのロックは、主に、次のような一部の非トランザクション ストレージ エンジンで使用されます。 MyISAM、MEMORY、CSV など。 テーブル ロックは通常、データ移行中に使用されます。
インテンション ロック: インテンション共有ロックとインテンション排他ロック
共有ロックを行に追加するための前提条件は、行のデータが配置されているテーブルが最初にロックを解除することです。インテンション共有ロックを取得します。 行に排他ロックを追加するための前提条件は、行のデータが配置されているテーブルが最初に目的の排他ロックを取得することです。
注: インテンション共有ロックとインテンション排他ロックはテーブル ロックであり、手動で作成することはできません。
インテンションロックを追加する必要がある理由
意向锁是为了告知mysql该表已经存在数据被加锁,而不需要逐行扫描是否加锁,提搞加锁的效率。
单个表锁定
lock tables saas.goods read,saas.account write; // 给saas库中的goods表加读锁,account表加写锁unlock tables; //解锁
全局表锁定
FLUSH TABLES WITH READ LOCK; // 所有库所有表都被锁定只读unlock tables; //解锁
注意: 在客户端和数据库断开连接时,都会隐式的执行unlock tables。如果要让表锁定生效就必须一直保持连接。
行锁
行锁升级为表锁(行锁实际是给索引加锁,如果没用索引而全表扫描,则会给全表加锁)
上图中where条件中,虽然template_name建立普通索引,但使用or关键字,导致template_name的索引失效,从而进行了全表扫描,锁定了整张表。
修改、删除某一行记录,且未提交事务时,该行会一直被行锁锁定
窗口1中删除某一行,但没有提交。窗口2中更新该行会一直处于阻塞中。
记录锁
间隙锁(Gap Locks)
经典参考文章
间隙锁的作用:防止幻读
间隙锁的目的是为了防止幻读,其主要通过两个方面实现这个目的:
(1)防止止间隙内有新数据被插入
(2)防止范围内已存在的数据被更新
innodb自动使用间隙锁的条件
(1)数据隔离级别必须为可重复读
(2)检索条件必须使用索引(没有使用索引的话,mysql会全表扫描,那样会锁定整张表所有的记录,包括不存在的记录,此时其他事务不能修改不能删除不能添加)
间隙锁锁定的区域
根据检索条件向左寻找最靠近检索条件的记录值A,作为左区间,向右寻找最靠近检索条件的记录值B作为右区间,即锁定的间隙为(A,B)。下图中,where number=5的话,那么间隙锁的区间范围为[4,11];
session 1:start transaction ;触发间隙锁的方式1:select * from news where number=4 for update ;触发间隙锁的方式2:update news set number=3 where number=4; session 2:start transaction ;insert into news value(2,4);#(阻塞)insert into news value(2,2);#(阻塞)insert into news value(4,4);#(阻塞)insert into news value(4,5);#(阻塞)insert into news value(7,5);#(执行成功)insert into news value(9,5);#(执行成功)insert into news value(11,5);#(执行成功)
next-key锁【临键锁】
next-key锁其实包含了记录锁和间隙锁,即锁定一个范围,并且锁定记录本身。InnoDB默认加锁方式是next-key 锁。
select * from news where number=4 for update ;
next-key锁锁定的范围为间隙锁+记录锁,即区间(2,4),(4,5)加间隙锁,同时number=4的记录加记录锁,即next-key锁的锁定的范围为(2,4],(4,5]。
记录锁、间隙锁、临间锁的区别
update news set number=0 where id>15
sql默认加的是next-key锁。根据上图,next-key锁的区间为(-∞,1],(1,5],(5,9],(9,11],(11,+∞),上面id>15,实际上next-key锁是加在[11,+∞)这个范围内,而不是(15,+∞)这个范围内。注意:需要使用锁的字段必须加索引,因为锁是加在索引上的,没有索引则加的表锁。
相关免费学习推荐:mysql数据库(视频)
以上がMySQL ロック メカニズムの再考の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。