营销型网站建设xywlcn,wordpress删除顶部设置菜单,国外做外贸哪个网站好些,山东住房建设部官方网站MVCC(Multi-Version Concurrency Control)多版本并发控制机制使用串行化隔离级别时#xff0c;mysql会将所有的操作加锁互斥#xff0c;来保证并发安全。这种方式必然降低并发性能。mysql在读已提交和可重复读隔离级别下#xff0c;对一行数据的读和写两个操作默认是不会通过…MVCC(Multi-Version Concurrency Control)多版本并发控制机制使用串行化隔离级别时mysql会将所有的操作加锁互斥来保证并发安全。这种方式必然降低并发性能。mysql在读已提交和可重复读隔离级别下对一行数据的读和写两个操作默认是不会通过加锁互斥来保证隔离性避免了频繁加锁互斥。那么具体是如何实现的呢首先要了解两个概念。准备建表语句CREATE TABLE product ( id int NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, price int DEFAULT NULL, PRIMARY KEY (id)) ENGINEInnoDB AUTO_INCREMENT21 DEFAULT CHARSETutf8;undo日志版本链我们向product表插入一条数据INSERT INTO mysql_demo.product (id, name, price) VALUES (1, apple, 10);此时mysql会同时向undo日志里写入一条记录。 trx_id为插入操作的事务id。这里随便写了一个80意思一下。 roll_pointer后面再说。这时候又来了一个事务对数据进行了修改。比如事务id 300修改price为20。此时mysql同样会在undo日志里写入一条记录。并且roll_pointer会指向前一条记录以此类推后续又有新的事务来操作这条记录就会形成一条版本链这条链就是undo日志版本链。每条数据对应着有一个undo日志版本链。对于insert和update操作mysql会向undo日志里添加一条记录。select操作不会产生记录。对于删除的情况可以认为是update的特殊情况会将版本链上最新的数据复制一份然后将trx_id修改成删除操作的trx_id同时在该条记录的头信息record header里的deleted_flag标记位写上true来表示当前记录已经被删除在查询时按照上面的规则查到对应的记录如果delete_flag标记位为true意味着记录已被删除则不返回数据。在来看下什么是read view。一致性试图read view机制read view的生成可重复读隔离级别事务开启后首次执行任何select时会生成当前事务的read-view在事务结束前不会变化。读已提交隔离级别事务开启后每次执行select时都会重新生成read-view。read view的组成这个视图由执行查询时所有未提交事务id数组数组里最小的id为min_id和已创建的最大事务idmax_id组成。我们来举个例子。Transaction 80 开启事务插入一条记录。并且commit;Transaction 100开启事务执行update。生成事务id 100。这里需要注意begin和select不会生成事务id所以加了一条无关的update生成事务id。update内容可以忽略。begin/start transaction 命令并不是一个事务的起点在执行到它们之后的第一个修改操作InnoDB表的语句事务才真正启动才会向mysql申请事务idmysql内部是严格按照事务的启动顺序来分配事务id的Transaction 200同上Transaction 300把价格修改成20了。并且commit了。select 1 select 不生成事务id。 事务开启后首次执行任何select时会生成当前事务的read-view。Transaction 400把价格修改成18了。read view的组成 未提交事务id数组数组里最小的id为min_id 已创建的最大事务idmax_id组成此时未提交事务id有100,200(80 已经提交了)。最小的id为100。 已创建的最大事务id为300。(注意read view 是在第5步生成的此时还没有Transaction 400)因此 read view为[100,200],300 min_id为100 max_id为300。 [100,200] 为视图数组。此时对应的undo日志版本链如下那么read view 的作用是什么呢read view的作用根据上面的结果我们可以将事务进行分类。因为事务的id是有序递增的。所以我们可以得出以下结论因为未提交事务的最小idmin_id为100所以小于100的事务都是已提交的。 Transaction 80因为已创建的最大事务idmax_id为300所以大于300的区域都是未开启事务。 Transaction 400 未开启理解为在执行select的时候没有开启。介于min_id和max_id之间的事务包含了未提交和已提交的事务。 Transaction 100,200,300那么mysql是如何通过read view和undo日志版本链实现并发事务之间的隔离的呢那就需要看下版本链比对规则了。版本链比对规则事务里的每一条select都需要从对应版本链里的最新数据开始逐条跟read-view做比对按照比对规则得到最终的快照结果。下面我们来看下版本链比对规则。如果 row 的 trx_id 落在绿色部分( trx_id 如果 row 的 trx_id 落在灰色部分( trx_idmax_id )表示这个版本是由将来启动的事务生成的row 的 trx_id 就是当前自己的事务是可见的否则不可见 如果 row 的 trx_id 落在黄色部分(min_id trx_id max_id)那就包括两种情况 若 row 的 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的若 row 的 trx_id 就是当前自己的事务是可见的否则不可见 若 row 的 trx_id 不在视图数组中表示这个版本是已经提交了的事务生成的可见。知道了版本链的比对规则下面我们通过实例来看下mysql的MVCC机制是如何工作的。实战演练可重复读Repeatable-ReadRR我们先以可重复读Repeatable-ReadRR为例可重复读隔离级别事务开启后首次执行任何select时会生成当前事务的read-view在事务结束前不会变化。案例一我们先以上面的情况为例来进行分析。此时的情况如下read view为 [100,200],300undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 300trx_id max_id。此时继续比对 trx_id 不在视图数组中可见。返回Transaction 300记录的数据信息。price 20;案例二Transaction 400在第10行执行了一次update。Transaction 100在第11,12行执行了两次update。然后select 1 13行执行了一次select。 我们来分析下这个select。因为RR隔离级别首次执行任何select时会生成当前事务的read-view在事务结束前不会变化。所以read view为 [100,200],300。没有变化。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 100trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。第二行Transaction 100分析同上第三行Transaction 400, trx_id max_id,不可见。Transaction 300trx_id max_id。此时继续比对trx_id 不在视图数组中可见。返回Transaction 300记录的数据信息。price 20;案例三继续向下Transaction 100在第15行commit。Transaction 200在第15,16行执行了两次update。然后select1 17行执行了一次select。 我们来分析下这个select。因为RR隔离级别首次执行任何select时会生成当前事务的read-view在事务结束前不会变化。所以read view为 [100,200],300。没有变化。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 200min_id trx_id max_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。下一行Transaction 200分析同上.Transaction 100trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。下一行Transaction 100分析同上。下一行Transaction 400, trx_id max_id,不可见。Transaction 300trx_id max_id。此时继续比对trx_id 不在视图数组中可见。返回Transaction 300记录的数据信息。price 20;案例四继续select2 17行执行了一次select。 我们来分析下这个select。RR隔离级别首次执行任何select时会生成当前事务的read-view。read view为 [200400],400。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 200trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。下一行Transaction 200分析同上.Transaction 100trx_id min_id。表示这个版本是已提交的事务生成的这个数据是可见的返回 price 16。案例五我们再来看一下如果select1 如果有update操作update操作会创建事务id我们假设是 500。Transaction 500 此时是如何读取到更新后的数据的。 来分析下15行。RR隔离级别首次执行任何select时会生成当前事务的read-view在事务结束前不会变化。read view为 [100,200],300。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 400trx_id max_id(read view是第一次select时生成的此时max_id仍然是 300)。表示这个版本是由将来启动的事务生成的是不可见的Transaction 500trx_id max_id。表示这个版本是由将来启动的事务生成的但row 的 trx_id 就是当前自己的事务是可见的所以可见返回 price 8。结论通过以上案例我们可以知道。 MVCC机制在RR中首次查询时会固定read view。后续和其他事务隔离开了其他事务对数据的操作不会影响到当前事务。读已提交Read-CommittedRC我们再以读已提交Read-CommittedRC为例读已提交隔离级别事务开启后每次执行select时都会重新生成read-view。案例一第9行没有变化我们来看第13行。read view的组成 未提交事务id数组数组里最小的id为min_id 已创建的最大事务idmax_id组成未提交事务id数组 100,200,400 ; min_id 100 ; max_id 400read view为 [100,200,400],400。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 100trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。下一行Transaction 100分析同上.Transaction 400, trx_id max_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。Transaction 300min_id trx_id max_id。不在视图数组中表示这个版本是已经提交了的事务生成的可见。返回 price 20。案例二来看第17行。read view的组成 未提交事务id数组数组里最小的id为min_id 已创建的最大事务idmax_id组成未提交事务id数组 200,400 ; min_id 200 ; max_id 400read view为 [200,400],400。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 200, trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。同上Transaction 100 trx_id返回 price 16。OK就分析到这里吧。希望对你有所帮助读已提交Read-CommittedRC我们再以读已提交Read-CommittedRC为例读已提交隔离级别事务开启后每次执行select时都会重新生成read-view。案例一第9行没有变化我们来看第13行。read view的组成 未提交事务id数组数组里最小的id为min_id 已创建的最大事务idmax_id组成未提交事务id数组 100,200,400 ; min_id 100 ; max_id 400read view为 [100,200,400],400。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 100trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。下一行Transaction 100分析同上.Transaction 400, trx_id max_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。Transaction 300min_id trx_id max_id。不在视图数组中表示这个版本是已经提交了的事务生成的可见。返回 price 20。案例二来看第17行。read view的组成 未提交事务id数组数组里最小的id为min_id 已创建的最大事务idmax_id组成未提交事务id数组 200,400 ; min_id 200 ; max_id 400read view为 [200,400],400。undo日志版本链如下套用版本链比对规则首先在版本链中找到最新数据。Transaction 200, trx_id min_id。继续分析 trx_id 在视图数组中表示这个版本是由还没提交的事务生成的不可见。同上Transaction 100 trx_id返回 price 16。OK就分析到这里吧。希望对你有所帮助