ロックとトランザクション分離レベルのMySQLの深い理解

ロック

図1に示すように、ロックが定義されています

    それは、同時に同じ共有リソース機構を使用する複数のスレッドまたはプロセスを調整するために使用されているロックされ

2、ロック分類

  •  楽観と悲観的ロック:パフォーマンスの分類から
  • データベース操作の種類から分類:読み取りおよび書き込みロック
  • 粒度分類操作から表および行ロック

2.1分類からパフォーマンス

2.1.1楽観的ロック
    名前が示唆するオプティミスティック・ロックの操作は、操作が並行性の問題(データを変更する他のスレッドを)持っていないではないだろうということは非常に楽観的である、それがロックされません。それはデータが、通常はバージョン番号またはCASメカニズムのアルゴリズムを変更することはできないがあるまで、しかしとき裁判官は再び他のスレッドを更新します。
バージョン番号2.1.1.1メカニズム
 実装:
  • 記録を削除するとき、現在のバージョンを取得します
  • このバージョンを持って、更新する場合
  • アップデート、セットバージョン= NEWVERSIONバージョン= oldVersionを行う場合
  • バージョンがない場合は、アップデートに失敗します
バージョンはカスタマイズすることができ、あなたはまた、バージョン番号としてタイムスタンプを使用することができます
例SQL:
update table set name = 'anna',version = version+1 where id = #{id} and version = #{version}
 
 
2.1.1.2 CASアルゴリズム
    別の技術楽観的ロック、複数のスレッドが同じ変数を更新し、同時にCASを使用しようとすると、一つのスレッドだけが変数テーブルの値を更新することができますが、他のスレッドが失敗しているが、失敗したと聖歌スレッドハングしませんし、私たちは、この競争は失敗に言われている、とあなたがもう一度試すことができます。
CAS操作は、3つのオペランドが含まれています。
  • あなたは、メモリ位置Vを読み書きする必要があります
  • 比較は、元の値に期待されています
  • Bは、新しい値を書き込もう
元の値V Aが一致の期待値とメモリ位置は、メモリ位置BとV A或いは、Aは、予想される元の値と一致しない場合、ノーオペレーションに書き込まれている場合。いずれの場合も、彼はCAS命令の前(現在の値を抽出することなく、CAS CAS成功したリターンのいくつかの特殊なケースでいる場合のみ)位置の値を返します。この事実と、楽観的ロックの競合は、一貫性のあるデータ更新の+原理をチェックするとき。
2.1.2悲観的ロック
    常に最悪のケースを想定し、それぞれの撮影データは、他のスレッドが変わるので、ロックされると思います。ロックされたら、別のスレッドの実行が同時に、実行の唯一のスレッドが、ロックを知っているのを待っている入り口の他のスレッドが解放されます。
悲観的ロックは広くJAVAとMySQLで使用されています
  •     MYSQLの読み取りロック、書き込みロック、行ロックなど 
  •     Javaのsynchronizedキーワード

使用推奨:
    多くの競合確率が小さい読む、楽観的ロックを使用
    書き込みロック、紛争の大きなチャンスは、悲観的ロックを使用します

データベースから2.2分級操作型

2.2.1読み取りロック
    読み込みロックは、ロックのクエリ操作で他のトランザクションを許可しますが、変更しないで、動作、すなわち共有ロック。
2.2.2書き込みロック
    排他ロックというロックは、すべての操作に他のことを行うことを許可されていない書き込みロック。

粒度分類操作2.3から

2.3.1テーブルロック
    名前が示すように、それはこのように大きな粒子サイズ、ブロックロックでロック、テーブル全体をロックし、オーバーヘッド小さい場合、デッドロック。しかし、ロックの競合が発生しやすい同時低効率の実装、。
2.3.2行ロック
    行ロックが遅く、大きな支出をロックする、このように小さいサイズでロック、ロックを操作する行は、デッドロックを生成することができます。しかし、競合をロックしやすい高効率、ないの同時実施。
    レコードロックの代わりに、行ロックInnoDBのためのインデックスの。インデックスが失敗した場合は、行ロックからテーブルロックにアップグレードされます。

MyISAMエンジンでのMySQLは唯一のテーブルロックをサポートし、それぞれの時間は、クエリは、テーブルプラスロックになると書き込みロックの動作を変更します。MyISAMテーブルは、トランザクションと行ロックをサポートしていないのMyISAMとInnoDBの間の最大の違いであるInnoDBのサポート行レベルのロックおよびトランザクション、しばらく。

第二に、トランザクション

1、トランザクションの定義

    トランザクション内のSQL文のセットからなる論理処理ユニット。

2、トランザクションの特性

    原子性、一貫性、分離性、耐久性:トランザクションは、4つのプロパティを持ちます。
  • アトミック:トランザクションのすべての操作がアトミックであるべきである、すなわち、いずれかの実行行いますか
  • 一貫性は:操作は一貫性を実行する前と後に提供されるデータを指します。関連するすべてのルールは、データの整合性を確保するために変更されたデータのトランザクションに適用されなければならないことをこれが意味。トランザクションの終了時に、すべてのデータ構造も正しくなければなりません。
  • アイソレーション:各トランザクションは、環境の独自の独立した中間状態を持って、トランザクションが外の世界とその逆に表示されません。
  • 永続性:でも、データベースのダウン後のトランザクションのコミット、永続的なデータベースのデータへの変更は、データベースのデータの状態を再起動するときに、まだトランザクションのコミット後の結果でなければなりません。

3、同時トランザクションによって引き起こされる問題に対処

  • ロストアップデート:2つの以上のトランザクションが同じ行を選択して、行を更新するために、初期値に基づいて選択し、各トランザクションは、他の事項の存在を知らないので、失われたアップデートの問題が発生した - 最終更新日カバレッジをアップデートを行うには、他の企業があります。
  • その他の事項の値を変更するために、読み取りトランザクションをしかし提出しないと、そのトランザクションがロールバックされた後、そのデータはトランザクションの一貫性を満たしていない、汚れがある現在のトランザクションによって読み取ら:ダーティー読み取り。
  • 非反復可能読み取り:現在のトランザクションの開始時には、データの行を読み出し、そのトランザクションが他の行の更新をコミットした後、トランザクションデータは再び同じ行を読み取り、結果を読み出したとき第1の相違点は、またはレコードが削除されているこれは、この現象は非反復可能読み取りと呼ばれています。
    そのトランザクションは、アイソレーションに準拠していない提出した他のトランザクションにデータを読み込みます。
  • マジック読書:Aの分離に準拠していない提出された新しいトランザクションBに取引データを読み込みます

4、トランザクション分離レベル

    同時トランザクションによる問題を解決するために、MySQLは私たちが選択するための4つのトランザクション分離レベルを提供します。
  • 非コミット読み取り(uncommitを読む):トランザクションを変更するには、コミットされていない読み取ることができます
  • コミット読み取り(コミット読み取り):コミットされたトランザクションを変更するために読むことができます
  • 反復可能読み取り(反復可能読み取り):進行中のトランザクションは、最初のクエリの結果が得られたときにのみスナップショットを使用しますその他のコミットされたトランザクションを変更するために読まれることはありません。この効果を達成するために、MVCC(マルチバージョン同時実行制御)機構にここで使用。
  • シリアル化(シリアライズ):状況はファントムは、そのような分離が非常に低い、少ない種を開発するための並行処理セクタを読み取る表示されませんので、このレベルで実行するためのシリアル形式へのトランザクションは、テーブルがロックされます使用。
    、データベースのトランザクション分離レベルより厳密に小さいにより引き起こさ次いで、同時副作用が、トランザクション分離レベルがある程度あるため効率は、また、より低い同時に実行され、トランザクションは明らかである、に「シリアル化」矛盾の「同時性」。
    だから、ビジネスシナリオに応じてデータの感度を選択するために、トランザクション分離レベルを選択するのが妥当でなければなりません。
 
ギャップはロック:ロックはファントムを使用して回避することができ、次のSQLステートメントを使用して、分離レベル反復可能読み取りでギャップを読みます
update account set name = 'tufeu' where id>=5  and id < 7;
在事务开头执行这一语句,可以使得其他事务无法在当前事务未提交前在id为5到7之间插入数据,这就是间隙锁
当然如果你不想真的修改数据的话,请保证间隙锁范围内没有数据。
 
 
seesion_1種類ギャップロックで
新しいデータ型のsession_2挿入中に、新たなID IDがブロックされているタイムアウトが生じる、空隙のロックレンジで、6をインクリメントしているので、挿入は失敗します。
不过由于大部分场景下不需要处理幻读的情况,所以平时要尽量避免间隙读,因为这样的确会降低并发效率
MVCC机制:
    mvcc机制底层由undo log实现,这里以一种较为简单的方式说明机制
首先要明确每个事务都有一个自己的id,事务的id只有在事务执行第一条sql语句时才会分配,mysql的事务id分配严格按照事务的创建顺序来进行。
我们可以看作每一条数据都有两个隐藏的字段创建事务id和删除事务id(可为空)
当我们修改一条数据的时候,不会直接修改,而是新增一条修改过后的数据id和原数据一致(这里是假设不是真实实现,不考虑id重复这个问题)
当我们删除的时候,会将当前做删除操作的事务id记录再”删除事务id“列上
当我们查询一条记录是,会创建一个查询快照,记录此刻的最大已提交事务id。
当我们再次查询的时候会在mysql底层带上过滤条件,创建事务id<=max(当前事务id,快照点已提交最大事务id) and 删除事务id>max(当前事务id,快照点已提交最大事务id)
查询结果不一定唯一,以创建事务id最大的那个为准。
id name balacne create_id del_id
1  a	100	11
2  b	200	12    12
3  c 	300	12
1  a	120	14
 
比如上面这几行数据,假如我们事务id为11 和 12 新增前三条数据,然后新开一个事务id为13的事务,进行查询操作select * form account,的到一个快照,并获得当前的最大已提交事务id为12,不去提交13,新创建一个事务id14,修改id为1的语句,这个时候,mysql会新增一条数据为修改过后的样子,有其事务创建id为14,这个时候我们用事务13去查询,查询语句回事 select * from account where 创建事务id<=max(当前事务id(13),快照点最大提交id(12)) and 删除事务id>max(当前事务id(13),快照点最大提交id(12)),如果没有删除事务id则忽略这个条件,这个时候应该可以看出我们查询出来的数据只会是第一条,因为第四条的创建事务id为14。
我们再看id为2的数据,根据上面的sql查询语句,我们可以看出他的删除事务id为12小于max(当前事务id,快照点最大提交id)所以无法查询到该数据。
 
优化建议:
  • 尽可能的让数据检索通过索引完成,避免无索引行锁升级为表锁
  • 合理设计索引,尽量缩小锁的范围
  • 极可能减少检索条件范围,避免间隙锁
  • 尽量控制事务大小,减少锁定资源量和时间长度,设计事务加锁的sql尽量放在事务最后执行
  • 尽可能使用低级别的事务隔离以提升并发效率
 
 
 
 

<wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





おすすめ

転載: www.cnblogs.com/qishanmozi/p/e972c92103cf3735872d88657a013df9.html