背景
- MySQLはほとんどのトランザクションストレージエンジンは、実際には、単純な行レベルロックを実現していません。リフティングに基づいて、同時パフォーマンスを考慮して、彼らは一般的に、マルチバージョン同時実行制御(MVCC)を達成しています。
- MVCCは、行レベルのロックの変形例を考えられているが、それは多くの場合、ロック操作を回避し、したがってコストを下げます。実装機構が異なっているが、ほとんどの非ブロック読み出し動作を実現するが、書き込み動作は、行をロックするだけでよいです。
- 多くのMVCC実装、一般的に楽観的同時実行性と悲観的同時実行制御があります。
- だけでMVCC READ COMMITTEDは、READ COMMITTEDとREPEATABLE READ 2の下で反復可能読み取り分離レベルの仕事。ので、他の2つは、分離レベルとMVCCと互換性がありませんREAD UNCOMMITEDはなく、行の現在のトランザクションのバージョンに沿ってよりも、最新のデータラインを読み取る常に非コミット読み取り。行ロックSERIALIZABLEのシリアル化は、すべて読みます。
概要
- MVCCは、MySQLにある
事务型存储引擎 InnoDB
サポート。 - 高並列トランザクションに対応、MVCCは単に少ないオーバーヘッドで、行ロックを追加するよりも効果的です。
- のみMVCC
READ COMMIT
とREPEATABLE READ
2つの分離レベルの下で作業。 - MVCCは楽観と悲観用いて達成することができます。
分析
データのバック行のInnoDBストレージエンジンは、データベース三つのフィールドに追加されません。
- 6バイトのトランザクションID(DB_TRX_ID)フィールド:トランザクションIDのこのマーク列の最新の更新、トランザクションを処理し、それぞれ、自動的に値が+1。
- 7バイトロールバックポインタ(DB_ROLL_PTR)フィールド:ロールバック・セグメントは、データの以前のバージョンを見つけるために、(アンドゥログレコード)ログアンドゥカレントレコードを向け、このポインタを介してです。
- DB_ROW_IDフィールドバイト6:クラスター化インデックスが他にクラスタ化インデックスをインデックスに、この値に含まれていないクラスタ化インデックス値DB_ROW_ID含む、InnoDBテーブルによって自動的に生成されます。
のはあなたのオンラインレコードの更新プロセスのトランザクションをお見せしましょう。
!
読み取りビュー
InnoDB内、それぞれが新しいものを作成し、ストレージエンジンは、現在アクティブなシステムにおけるトランザクションのリストのコピーを作成する(だろう
read view
)、トランザクションIDのコピーを保存し、他の現在のシステムのリストは、このトランザクションで見られるべきではないです。トランザクション内のユーザは、レコードの時間の行を読み取るときに、ラインの現在のバージョンは、読み出しビューと比べて比較アルゴリズムによって比較を良好にINNODBう。
比較アルゴリズム
現在のトランザクションIDのラインがtrx_id_current、銀行の最初のトランザクションIDでread_view trx_id_firstさがあると仮定すると、最新のトランザクションIDはtax_id_lastです。
trx_id_currentは<trx_id_first、それが意味している場合
現在のトランザクションに銀行のレコードを読み込む場合、トランザクションIDは、他よりも小さくなるようにします。現在のすべての銀行の記録に関する事項、現在のトランザクションが銀行の記録に最初の読み取りで、変更が行われなかったが、まだ現在のトランザクションのトランザクションの前の行にデータを提出していないことを意味したがって、現在のトランザクションは、テーブルに直接それを取ることができる安定したデータ!
trx_id_currentは> tax_id_last、それが意味している場合
現在のトランザクションに銀行のレコードを読み込む場合、トランザクションIDは、他のread_viewトランザクションIDよりも大きいです。現在のすべてのレコードは、銀行の業務に関連することを意味し、時事問題は、最後の行がレコードに読み込まあります。DB_ROLL_PTRは、最新のアンドゥログのバージョン番号で尖ったアウトのロールバック・セグメントの行へのポインタを必要とし、その後の反復が見つけることアンドゥ・ログ内のダウン、レイヤーを続けていきよると、最終的にわかります安定したデータを!
trx_id_first <trx_id_current <tax_id_last、同上。
对比READ COMMITED
和REPEATABLE READ
READ COMMITED
读已提交,只能解决脏读问题,但是不能解决不可重复读问题,所以每次都能读取到最新一份数据快照。
REPEATABLE READ
可重复读,解决了脏读和不可重复读的问题,所以能读到事务开始前时的数据版本。
- 使得
READ COMMITED
级别能够保证, 只要是当前语句执行前已经提交的数据都是可见的。 - 使得
REPEATABLE READ
级别能够保证, 只要是当前事务执行前已经提交的数据都是可见的。
总结
- 一般我们认为MVCC有下面几个特点:
- 每行数据都存在一个版本,每次数据更新时都更新该版本
- 修改时Copy出当前版本, 然后随意修改,各个事务之间无干扰
- 保存时比较版本号,如果成功(commit),则覆盖原记录, 失败则放弃copy(rollback)
- 就是每行都有版本号,保存时根据版本号决定是否成功,听起来含有乐观锁的味道, 因为这看起来正是,在提交的时候才能知道到底能否提交成功
- 而InnoDB实现MVCC的方式是:
- 事务以排他锁的形式修改原始数据
- 把修改前的数据存放于undo log,通过回滚指针与主数据关联
- 修改成功(commit)啥都不做,失败则恢复undo log中的数据(rollback)
- 二者本质的区别是 InnoDB 使用了 拍他锁。
- InnoDB 的实现算不上 MVCC,因为没有实现核心的多版本共存,undo log 中的内容只是串行化的结果,记录了多个事务的过程,不属于多版本共存。
- 因为InnoDB使用的MVCC中结合了排他锁, 不是纯的MVCC, 所以第一类更新丢失是不会出现了, 一般说更新丢失都是指第二类丢失更新。