マルチバージョン同時実行制御MVCCは、反復可能読み取りを実現します

マルチバージョン同時実行制御MVCCは、反復可能読み取りを実現します

参照

高性能 MySQL 第3版 1.4 多版本并发控制

MVCCは、データを保存することで、ある時点でのスナップショットに実装されています。MVCC異なるストレージエンジン、一般的に楽観的同時実行性と悲観的同時実行制御の異なる実装。

InnoDBは達成することMVCCです

名詞

系统版本号 事务版本号 记录创建时间 记录删除时间

InnoDBのMVCCは、各ライン記録後に実装2つの列を格納することによって隠されています。行を作成するための時間保存すると、保存されたタイムラインを削除します。確かに時間の値が保存されますが、システムのバージョン番号されません。それぞれが新しいトランザクションを開始し、システムが自動的にバージョン番号をインクリメントします。取引システムのバージョン番号は、トランザクションの開始時刻のバージョン番号です。

反復可能読み取りMVCCの実行プロセス

事务版本号是事务开始时刻的系统版本号 每开始一个新的事务,系统版本号都会自动递增

選択する

戻り値のレコード、次の条件が満たされます

创建时间 <= 当前事务版本号 && ( 删除时间 == null || 删除时间 > 当前事务版本号 )

インサート

插入记录的创建时间 = 当前系统版本号

作成し、新たに挿入されたレコードが現在のシステムのバージョン番号に設定され、時間がnullの削除。

削除

被删除记录的删除时间 = 当前系统版本号

記録された時間を削除するには、DELETEは、現在のシステムのバージョン番号、墓石、とすることができ、実際に削除されていないデータに設定されています。

更新

被更新记录的原记录的删除时间 = 当前系统版本号 新插入记录的创建时间 = 当前系统版本号

時間は、論理削除元のレコードで、現在のシステムのバージョン番号、元のレコードセットを削除するように更新されます。現在のシステムのバージョン番号のために作成された新しいレコードを挿入します。

MVCCは、単独で働いて2レベルがコミットおよび反復読み取る読み取り、及び他の分離レベルは、このメカニズムを使用していません。常にではなく、行の現在のトランザクションのバージョンに合わせてよりも、最新のデータラインを読んでコミットされていない読んで、すべての行のseriablizableロックをお読みください。

MVCCソースの解析

http://www.ningoo.net/html/tag/mysql

http://blog.sina.com.cn/s/blog_4673e603010111ty.html

https://blog.csdn.net/joy0921/article/details/80128857

https://blog.csdn.net/u012919352/article/details/87984786

https://mp.weixin.qq.com/s?__biz=MzIxNTQ3NDMzMw==&mid=2247483670&idx=1&sn=751d84d0ce50d64934d636014abe2023&chksm=979688e4a0e101f2a51d1f06ec75e25c56f8936321ae43badc2fe9fc1257b4dc1c24223699de&scene=21#wechat_redirect

https://dev.mysql.com/doc/refman/5.5/en/innodb-consistent-read.html

https://blog.csdn.net/joy0921/article/details/80128857

三つのフィールドを非表示にします

ROW_IDはdb_roll_pt IDのロールバックトランザクションレコードポインタのIDをdb_trx_id

  • まず、各データの行ならびにInnoDBが行修飾の前バージョンの履歴を指すためDB_ROLL_PTポインタをロールバックします

  • 挿入するときに、新しいデータは、対応するロールバックポインタに記録されているNULLです。
  • 現在のレコードが主キーを持っている場合、レコードIDは、ROW_IDが生成されません
  • ログアンドゥビューを読みます

行によって決定読み取るビューが表示され

次のように特定決意プロセスです。

RR分離レベルの下では、各トランザクションの時間が始まった時に、すべてのアクティブなトランザクションがリスト(読み取りビュー)に、現在のシステムにコピーされます
RCの分離レベルの下で、各ステートメントの開始、意志現在のシステムリストのコピーへのすべてのアクティブなトランザクション(ビューを読みます)

  • 「唐チェン-2016PGアセンブリ - マルチデータベースバージョンの実装のインサイダーの.pdf」

https://myslide.cn/slides/3542

読み取りビューのMySQLの···InnoDBのソースコード解析、ロールバックセグメントとパージ処理はじめ https://yq.aliyun.com/articles/560506

mysql> show engine innodb status\G;
------------
TRANSACTIONS
------------
Trx id counter AC16
Purge done for trx's n:o < AC14 undo n:o < 0
History list length 1079
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION AC15, not started
MySQL thread id 4, OS thread handle 0x43c, query id 133 localhost 127.0.0.1 root
show engine innodb status
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G;

https://www.cnblogs.com/itcomputer/articles/5084611.html

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G;
*************************** 1. row ***************************
                    trx_id: AC16
                 trx_state: RUNNING
               trx_started: 2019-08-03 11:50:27
     trx_requested_lock_id: NULL
          trx_wait_started: NULL
                trx_weight: 0
       trx_mysql_thread_id: 10
                 trx_query: NULL
       trx_operation_state: NULL
         trx_tables_in_use: 0
         trx_tables_locked: 0
          trx_lock_structs: 0
     trx_lock_memory_bytes: 376
           trx_rows_locked: 0
         trx_rows_modified: 0
   trx_concurrency_tickets: 0
       trx_isolation_level: READ COMMITTED
         trx_unique_checks: 1
    trx_foreign_key_checks: 1
trx_last_foreign_key_error: NULL
 trx_adaptive_hash_latched: 0
 trx_adaptive_hash_timeout: 10000
1 row in set (0.00 sec)

私はAC18 AC17、トランザクションカウンタが= AC19 2つのトランザクションをオープンしました

mysql> show engine innodb status\G;
------------
TRANSACTIONS
------------
Trx id counter AC19
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX\G;
*************************** 1. row ***************************
                    trx_id: AC18
                 trx_state: RUNNING
               trx_started: 2019-08-03 11:56:40
*************************** 2. row ***************************
                    trx_id: AC17
                 trx_state: RUNNING
               trx_started: 2019-08-03 11:55:08
            
mysql> SELECT tx.trx_id
    -> FROM information_schema.innodb_trx tx
    -> WHERE tx.trx_mysql_thread_id = connection_id();
+--------+
| trx_id |
+--------+
| AC17   |
+--------+
1 row in set (0.07 sec)
mysql> SELECT tx.trx_id
    -> FROM information_schema.innodb_trx tx
    -> WHERE tx.trx_mysql_thread_id = connection_id();
+--------+
| trx_id |
+--------+
| AC18   |
+--------+
1 row in set (0.00 sec)
mysql> SELECT tx.trx_id
    -> FROM information_schema.innodb_trx tx
    -> WHERE tx.trx_mysql_thread_id = connection_id();
Empty set (0.00 sec)

https://www.jdon.com/51517

RR(ギャップロックを除く)分離レベルとRC異なる分離レベルは、時間差のスナップショットを作成することです。むしろ、トランザクションの開始時にRR分離レベル、最初の読み取り創造の見解を読んで、RCの分離レベルは声明で読み取りビューを作成するには、開始時間です。

作成/読み込みビューがtrx_sys->ミューテックスを保持する必要性を閉鎖し、劣化システム性能、このバージョン5.7が最適化され、トランザクションがセッションをコミット読み取りビューは、読取り専用キャッシュされますトランザクションを。

Read view中保存的trx_sys状态主要包括

low_limit_id:high water mark,大于等于view->low_limit_id的事务对于view都是不可见的
up_limit_id:low water mark,小于view->up_limit_id的事务对于view一定是可见的
low_limit_no:trx_no小于view->low_limit_no的undo log对于view是可以purge的
rw_trx_ids:读写事务数组

Read view创建之后,读数据时比较记录最后更新的trx_id和view的 high/low water mark和读写事务数组即可判断可见性。
如前所述,如果记录最新数据是当前事务trx的更新结果,对应当前read view一定是可见的。

除此之外可以通过high/low water mark快速判断:

trx_id < view->up_limit_id的记录对于当前read view是一定可见的;
trx_id >= view->low_limit_id的记录对于当前read view是一定不可见的;
如果trx_id落在[up_limit_id, low_limit_id),需要在活跃读写事务数组查找trx_id是否存在,如果存在,记录对于当前read view是不可见的。
storage/innobase/read/read0read.c
http://blog.sina.com.cn/s/blog_4673e603010111ty.html

ストレージ/あるInnobase /含ん/ read0read.ic

view->n_trx_ids 数量
view->up_limit_id
view->low_limit_id
/*********************************************************************//**
Checks if a read view sees the specified transaction.
@return TRUE if sees */
UNIV_INLINE
ibool   
read_view_sees_trx_id(
/*==================*/
    const read_view_t*  view,   /*!< in: read view */
    trx_id_t        trx_id) /*!< in: trx id */
{
    ulint   n_ids;
    ulint   i;

    if (trx_id < view->up_limit_id) {

        return(TRUE);
    }

    if (trx_id >= view->low_limit_id) {

        return(FALSE);
    }

    /* We go through the trx ids in the array smallest first: this order
    may save CPU time, because if there was a very long running
    transaction in the trx id array, its trx id is looked at first, and
    the first two comparisons may well decide the visibility of trx_id. */

    n_ids = view->n_trx_ids;

    for (i = 0; i < n_ids; i++) {
        trx_id_t    view_trx_id
            = read_view_get_nth_trx_id(view, n_ids - i - 1);

        if (trx_id <= view_trx_id) {
            return(trx_id != view_trx_id);
        }
    }

    return(TRUE);
}

ストレージ/あるInnobase /含ん/ read0read.h

struct read_view_struct{
    ulint       type;   /*!< VIEW_NORMAL, VIEW_HIGH_GRANULARITY */
    undo_no_t   undo_no;/*!< 0 or if type is
                VIEW_HIGH_GRANULARITY
                transaction undo_no when this high-granularity
                consistent read view was created */
    trx_id_t    low_limit_no;
                /*!< The view does not need to see the undo
                logs for transactions whose transaction number
                is strictly smaller (<) than this value: they
                can be removed in purge if not needed by other
                views */
    trx_id_t    low_limit_id;
                /*!< The read should not see any transaction
                with trx id >= this value. In other words,
                this is the "high water mark". */
    trx_id_t    up_limit_id;
                /*!< The read should see all trx ids which
                are strictly smaller (<) than this value.
                In other words,
                this is the "low water mark". */
    ulint       n_trx_ids;
                /*!< Number of cells in the trx_ids array */
    trx_id_t*   trx_ids;/*!< Additional trx ids which the read should
                not see: typically, these are the active
                transactions at the time when the read is
                serialized, except the reading transaction
                itself; the trx ids in this array are in a
                descending order. These trx_ids should be
                between the "low" and "high" water marks,
                that is, up_limit_id and low_limit_id. */
    trx_id_t    creator_trx_id;
                /*!< trx id of creating transaction, or
                0 used in purge */
    UT_LIST_NODE_T(read_view_t) view_list;
                /*!< List of read views in trx_sys */
};
trx_id_t    trx_id = row_get_rec_trx_id(rec, index, offsets); //获取记录上的TRX_ID这里需要解释下,我们一个查询可能满足的记录数有多个。那我们每读取一条记录的时候就要根据这条记录上的TRX_ID判断这条记录是否可见
return(view->changes_visible(trx_id, index->table->name)); //判断记录可见性
--------------------- 
作者:仲培艺 
来源:CSDN 
原文:https://blog.csdn.net/joy0921/article/details/80128857 
版权声明:本文为博主原创文章,转载请附上博文链接!
对于不可见的记录都是通过row_vers_build_for_consistent_read函数查询UNDO构建老版本记录,直到记录可见。

这里需要说明一点 不同的事务隔离级别,可见性的实现也不一样:

READ-COMMITTED 
事务内的每个查询语句都会重新创建Read View,这样就会产生不可重复读现象发生

REPEATABLE-READ 
事务内开始时创建Read View , 在事务结束这段时间内 每一次查询都不会重新重建Read View , 从而实现了可重复读。

trx_sys-> trx_list

https://blog.csdn.net/longxibendi/article/details/42012629

Read view创建之后,读数据时比较记录最后更新的trx_id和view的high/low water mark和读写事务数组即可判断可见性。

https://cloud.tencent.com/developer/ask/210171

https://blog.jcole.us/innodb/

https://github.com/jeremycole/innodb_ruby/wiki

[root@instance-fjii60o3 ~]# gem install innodb_ruby
-bash: gem: command not found

https://rubygems.org/

[root@instance-fjii60o3 develop]# wget https://rubygems.org/rubygems/rubygems-3.0.4.tgz
-rw-r--r-- 1 root root    883664 Jun 14 11:35 rubygems-3.0.4.tgz

Linuxのインストール宝石https://www.csdn.net/gather_2b/MtjaUgysNDYzNS1ibG9n.html

[root@instance-fjii60o3 rubygems-3.0.4]# bin/gem
/usr/bin/env: ruby: No such file or directory

Linuxはルビーをインストール

https://www.cnblogs.com/xuliangxing/p/7132656.html?utm_source=itdadao&utm_medium=referral

[root@instance-fjii60o3 rubygems-3.0.4]# yum list install | grep ruby
Error: No matching Packages to list
[root@instance-fjii60o3 rubygems-3.0.4]# yum list installed | grep ruby
ruby.x86_64                            2.0.0.648-35.el7_6             @updates  
ruby-irb.noarch                        2.0.0.648-35.el7_6             @updates  
ruby-libs.x86_64                       2.0.0.648-35.el7_6             @updates  
rubygem-bigdecimal.x86_64              1.2.0-35.el7_6                 @updates  
rubygem-io-console.x86_64              0.4.2-35.el7_6                 @updates  

Linuxはgitのインストール

[root@instance-fjii60o3 ~]# yum install git
[root@instance-fjii60o3 ~]# git clone https://github.com/jeremycole/innodb_ruby.git
[root@instance-fjii60o3 rubygems-3.0.4]# gem install --user-install innodb_ruby

WARNING:  You don't have /root/.gem/ruby/bin in your PATH,
      gem executables will not run.

ルビーRubyGemsの(GEM)パッケージマネージャを学ぶのインストールと使用

https://blog.csdn.net/luyaran/article/details/85698936

[root@instance-fjii60o3 rubygems-3.0.4]# yum list installed | grep ruby
Existing lock /var/run/yum.pid: another copy is running as pid 11250.
Another app is currently holding the yum lock; waiting for it to exit...
  The other application is: yum
    Memory :  90 M RSS (408 MB VSZ)
    Started: Sat Aug  3 14:39:05 2019 - 16:44 ago
    State  : Sleeping, pid: 11250

システムアクティブなトランザクションID

MVCCの可視性https://blog.csdn.net/taozhi20084525/article/details/19501075

[root@instance-fjii60o3 develop]# yum localinstall mysql-community-server-8.0.13-1.el7.x86_64.rpm 
Loaded plugins: langpacks, versionlock
Existing lock /var/run/yum.pid: another copy is running as pid 11250.
Another app is currently holding the yum lock; waiting for it to exit...
  The other application is: yum
    Memory :  89 M RSS (408 MB VSZ)
    Started: Sat Aug  3 14:39:05 2019 - 1:15:13 ago
    State  : Traced/Stopped, pid: 11250
[root@instance-fjii60o3 develop]# tar -xvf mysql-8.0.13-1.el7.x86_64.rpm-bundle.tar -C mysql8.0
mysql-community-client-8.0.13-1.el7.x86_64.rpm
mysql-community-embedded-compat-8.0.13-1.el7.x86_64.rpm
mysql-community-libs-8.0.13-1.el7.x86_64.rpm
mysql-community-server-8.0.13-1.el7.x86_64.rpm
tar: Unexpected EOF in archive
tar: rmtlseek not stopped at a record boundary
tar: Error is not recoverable: exiting now

RubyのツールInnoDBのレコード構造解析

https://cloud.tencent.com/developer/ask/210171

https://github.com/jeremycole/innodb_ruby/wiki

  1. ルビーのインストール

  2. gem install innodb_ruby

    InnoDBのフォーマットの解析ツール

https://rubygems.org/gems/innodb_ruby/versions

https://www.cnblogs.com/zengkefu/p/5678356.html

Linuxは、ファイルサイズを表示します

[root@instance-fjii60o3 ~]# du -sh MySQL-5.5.62-1.el7.x86_64.rpm-bundle.tar 
2.1M    MySQL-5.5.62-1.el7.x86_64.rpm-bundle.tar
[root@instance-fjii60o3 ~]# du -sh develop/
1.1G    develop/

MySQLの行レベルのロックを理解するために5分- 「ボトムMysqlのロックを取得」 https://blog.csdn.net/zcl_love_wx/article/details/81983267

テーブルレベルロック、ページレベルのロック、行レベルロック:ロック3つのレベルがあるのMySQL

  • 各タイムロックは、データロック機構の行は行レベルロック(ローレベル)です。行レベルのロックは、MySQL独自の方法をロックされていないが、他のストレージエンジンによってそれ自体が実装さ

  • 主InnoDBストレージエンジンの使用行レベルのロック、およびMySQL分散ストレージエンジンNDBCLUSTER

InnoDBテーブルの行レベルのロックは、2つのタイプに分けられる:共有ロック排他ロック、および行レベルのロックとテーブル・レベルのロックを可能にするために、実装プロセスのロック機構で共存し、InnoDBはまた、使用意図的ロック(表レベルのロックを)のコンセプトは、我々は共有意図的ロックと意図排他ロックの両方を持つことになります。

おすすめ

転載: www.cnblogs.com/mozq/p/12093752.html