当前位置: 首页 > news >正文

有经验的邯郸网站建设霍邱网站设计

有经验的邯郸网站建设,霍邱网站设计,海南省住房与城乡建设厅网站,下载微信找回微信1.前言 我们在MySQL实战之事务隔离#xff1a;为什么你改了我还看不见讲过事务隔离级别的时候提到过#xff0c;如果是可重复读隔离级别#xff0c;事务T启动的时候会创建一个视图read-view,之后事务T执行期间#xff0c;即使有其他事务修改了数据#xff0c;事务T看到的…1.前言 我们在MySQL实战之事务隔离为什么你改了我还看不见讲过事务隔离级别的时候提到过如果是可重复读隔离级别事务T启动的时候会创建一个视图read-view,之后事务T执行期间即使有其他事务修改了数据事务T看到的仍然跟在启动时看到一样。也就是说一个在可重复读隔离级别下执行的事务好像与世无争不受外界影响。 但是我们在MySQL实战之行锁功过怎么减少行锁对性能的影响分享行锁的时候又提到一个事务要更新一行如果刚好有另外一个事务拥有这一行的行锁它又不能这么超然了会被锁住进入等待状态。问题是既然进入了等待状态那么等这个事务自己获取到行锁要更新数据的时候它读到的值又是什么呢 我们来看一个例子 mysql CREATE TABLE t (id int(11) NOT NULL,k int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB; insert into t(id, k) values(1,1),(2,2);这里我们需要注意的是事务的启动时机 begin/start transaction命令并不是一个事务的起点在执行到他们之后第一个操作InnoDB表的语句事务才真正启动。如果你想要马上启动一个事务可以使用start transaction with consistent snapshot这个命令。 第一种启动方式一致性视图是在执行第一个快照读语句时创建的第二种启动方式一致性视图是在执行start transaction with consistent snapshot时创建的。 在这个例子中事务C没有显示的使用begin/commit,表示这个update语句本身就是一个事务语句完成的时候会自动提交。事务B在更新了行之后查询事务A在一个只读事务中查询并且时间顺序是在事务B的查询之后。 这时如果我告诉你事务B查到的k值是3而事务A查到的k值是1你是不是感觉是有点晕呢 所以本篇文章主要就是说明白这个问题希望借由把这个疑惑解开的过程能够帮助你对InnoDB的事务和锁有更进一步的理解。 在MySQL中有两个视图的概念 一个是view。它是一个用于查询语句定义的虚拟表在调用的时候执行查询语句并生成结果。创建视图的语法是create view…而他的查询和表一样。另一个是InnoDB在实现MVCC时用到的一致性读视图即consistent read view用于支持RCread committed 读已提交和RRRepeatable Read 可重复读隔离级别的实现。 他没有物理结构作用是事务执行期间用来定义”我能看到什么数据“。 在MySQL实战之事务隔离为什么你改了我还看不见中我们讲过了MVCC的实现逻辑。今天为了说明查询和更新的区别我们换一个方式来说明把read view拆开。你可以结合这两篇的说明来更深一步的理解MVCC。 2. 快照在MVCC里是怎么工作的 在可重复读隔离级别下事务在启动的时候就拍了个快照。注意这个快照是基于整库的。 这是你会说这看上去不太现实啊如果一个库有100G那么我启动事务MySQL就要拷贝100G的数据出来这个过程的多慢呀。可是我平时的事务执行起来很快呀。 实际上我们并不需要拷贝100G的数据。我们先来看看这个快照读是怎么实现的。 InnoDB里面每个事务有一个唯一的事务ID叫做transaction id。它是事务开始的时候向InnoDB的事务系统申请的是按照申请顺序严格递增的。 而每行数据也都是有多个版本的。每次事务更新数据的时候都会生成一个新的数据版本并且把transaction id赋值给这个数据版本的事务ID即为row trx_id…同时旧的数据版本要保留并且在新的数据版本中能够有信息可以直接拿到它。 也就是说数据库中的一行记录其实可能有多个版本每个版本由自己的row trx_id. 如下图所示就是一个记录被多个事务连续更新后的状态。 图中虚线框里是同一行数据的4个版本当前最新版本是V4k的值是22它是被transaction id为25的事务更新的因此它的row trx_id也是25. 你可能会问前面的文章不是说语句更新会生成undo log(回滚日志)吗那么undo log在哪呢 实际上上图中三个虚线箭头就是undo log而V1、V2、V3并不是物理上真实存在的而是每次需要的时候根据当前版本和undo log计算出来的。比如需要V2的时候就是通过V4依次执行U3、U2算出来。 明白了多版本和row trx_id的概念后我们再来想一下InnoDB是怎么定义那个100G的快照的。 按照可重复读的定义一个事务启动的时候能够看到所有已经提交的事务结果但是之后这个事务执行期间其他事务的更新对它不可见。 因此一个事务只需要在启动的时候声明说以我启动的时刻为准如果一个数据版本是在我启动之前生成的就认如果是我启动以后生成的我就不认我必须要找到它的上一个版本。 当然如果上一个版本也不可见那就继续往前找。还有如果这个事务自己更新的数据还是要认的。 在实际上InnoDB为每个事务构造了一个数组用来保存这个事务启动瞬间当前正在活跃的所有事务ID活跃指的是启动了但未提交。 数组里面事务ID的最小值为低水位当前系统里面已经创建过的事务ID的最大值1记为高水位。 这个视图数组和高水位就组成当前事务的一致性视图。 而数据版本的可见性规则就是基于数据row trx_id和这个一致性视图的对比结果得到的。 这个视图数组所有的rox trx_id分成了以下几种情况 这样对于当前事务的启动瞬间来说一个数据版本的rox trx_id有以下几种可能 如果落在绿色部分表示这个版本是已经提交的事务或者当前事务自己生成的这个数据是可见的。如果落在红色部分表示这个版本是由将来启动的事务生成的是肯定不可见的如果落在黄色部分那就包括两种情况 a. 若rox trx_id在数组中表示这个版本是由还没有提交的事务生成的不可见 b. 若rox trx_id不在数组中表示这个版本是已经提交了的事务生成的可见 比如,对于图2中的数据来说如果有一个事务它的低水位是18那么当访问这一行数据时就会从V4通过U3计算出V3所以在它看来这一行的只是11. 你看有了这个声明后系统里面随后发生的更新是不是就跟这个事务看到的内容无关了呢因为之后的更新生成的版本一定属于上面2或者3a的情况而对它来说这些新的数据版本是不存在的所以这个事务的快照就是静态的了。 所以你现在知道了InnoDB利用了所有数据都有多个版本的特性实现了秒级创建快照的能力。 接下来我们继续看一下图1中的三个事务分析下事务A的语句返回的结果为什么是k1. 这里我们不妨做一个假设 事务A开始前系统里面只有一个活跃事务ID是99事务A、B、C的版本号分别是100、101、102且当前系统只有这四个事务三个事务开始前(1,1)这一行数据的rox trx_id是90 这样事务A的视图数组就是[99, 100],事务B的视图数组是[99,100,101]事务C的视图数组是[99,100,101,102]。 为了简化分析我先把其他的干扰语句去掉只画出跟事务A查询逻辑相关的操作 从图中可以看到第一个有效更新的是事务C把数据从(1,1)改成了(1,2)。这时候这个数据的最新版本rox trx_id是102而90这个版本已经成为历史版本。 第二个有效更新是事务B把数据从(1,2)改成了(1,3)。这时候这个数据的最新版本rox trx_id是101而102又成为了历史版本。 你可能注意到了在事务A查询的时候其实事务B还没有提交但是它生成的(1,3)这个版本已经变成当前版本了。但这个版本对事务A必须是不可见的否则就变成了脏读了。 好现在事务A来读取数据了它的视图是[99,100]。当然了读数据都是从当前版本读起的。所以事务A查询语句读数据的流程是这样的 找到(1,3)的时候判断出rox trx_id101比高水位打处于红色区域不可见接着找到上一个历史版本一看rox trx_id102,比高水位打处于红色区域不可见再往前找终于找到了(1,1)他的rox trx_id90比低水位小处于绿色区域可见 这样执行下来虽然期间这一行数据被修改过但是事务A不论在什么时候查询看到这行数据的结果都是一致的所以我们称之为一致性读。 这个判断规则是从代码逻辑直接转译过来的但是正如你所见用于人肉分析可见性很麻烦。 所以我来给你翻译一下。一个数据版本对于一个事务视图来说除了自己的更新总是可见外有三种情况 版本未提交不可见版本已提交但是在视图创建后提交的不可见版本已提交而且是在视图创建前提交的可见 现在我们用这个规则来判断图4中的查询结果事务A的查询语句的视图数组是在事务A启动的时候生成的这时候 (1,3)还没有提交属于情况1不可见(1,2)虽然已经提交但是在事务A视图创建后属于情况2可见(1,1)虽然已经提交但是是在事务A视图创建前属于情况3可见 你看去掉数字对比后只用时间的先后顺序来判断分析起来是不是轻松多了所以后面我们就用这个规则来分析。 3.更新逻辑 细心的同学可能有疑问了事务B的update语句如果按照一致性读好像结果不对哦 你看图5 中事务B的视图数组是先生成的之后事务C才提交的不是应该看不见(1,2)吗怎么能算出(1,3)来 是的如果事务B在更新之前查询一次数据这个查询返回的k确实是1. 但是当它要去更新数据的时候就不能在历史版本上更新了否则事务C的更新就丢失了。因此事务B此时的set kk1是在(1,2)的基础上进行的操作。 所以这里就用了这样一条规则更新数据都是先读后写的而这个读只能读当前值成为当前读。 因此在更新的时候当前读拿到的数据是(1,2)更新后生成了新版本数据(1,3)这个新版本的rox trx_id是101. 所以在执行事务B查询语句的时候一看自己的版本号是101最新数据的版本号也是101是自己的更新可以直接使用所以查询得到的k值是3. 这里我们提到了一个概念叫做当前读。其实处理update语句外select语句如果加锁也是当前读。 所以如果把事务A的查询语句select * from t where id 1修改一下加上lock in share mode或for update也都可以读到版本号是101的数据返回k3.下面这两个select就是分别加了读锁(S锁共享锁)和写锁X锁排他锁. mysql select k from t where id1 lock in share mode; mysql select k from t where id1 for update;再往前一步假设事务C不是马上提交的而是变成下面的事务C‘会怎么样呢 事务C’的不同是更新后并没有马上提交在它提交前事务B的更新语句先发起了。前面说过了虽然事务C’还没提交但是12这个版本已经生成了并且是当前的最新版本。那么事务B的更新语句会怎么处理呢 这时候我们在上一篇文章中提到的“两阶段锁协议”就要上场了。事务C’没提交也就是说12这个版本上的写锁还没释放。而事务B是当前读必须要读取最新版本而且必须要加锁因此就被锁住了必须等到事务C‘释放这个锁才能继续它的当前读 到这里我们把一致性读、当前读、和行锁就串起来了。 现在我们在回到文章的开头的问题事务的可重复读的能力是怎么实现的 可重复读的核心就是一致性读而事务更新数据的时候只能用当前读。如果当前的记录的行锁被其他事务占用的话就需要进入锁等待。 而读提交的逻辑和可重复读的逻辑类似他们最主要的区别是 在可重复读的隔离级别下只需要在事务开始的时候创建一致性视图之后事务里的其他查询都公用这个一致性视图在读提交隔离级别下每个语句执行前都会重新算出一个新的视图 那么我们再看一下在读提交隔离级别下事务A和事务B的查询语句查到的k分别是多少呢 这里需要说明一下start transaction with consistent snapshot;的意思是从这个语句开始创建一个持续整个事务的一致性快照。所以在读提交隔离级别下这个用法就没意义了等效于 start transaction。 下面是读提交的状态图可以看到这两个查询的创建视图数组的时机发生了变化就是图中的read view框 这时事务A的查询语句的视图数组是在执行这个语句的时候创建的时序上(1,2)、(1,3)的生成时间都在创建这个视图数组的时刻之前但是在这个时刻 (1,3)还没有提交属于情况1不可见(1,2)已经提交属于情况3可见。 所以这时候事务A查询语句返回的是k2事务B查询结果是k3; 4.小结 InnoDB的行数据有多个版本每个数据版本由自己的row trx_id每个事务或者语句有自己的一致性视图。普通查询语句是一致性读一致性读会根据row trx_id和一致性视图确定数据版本的可见性。 对于可重复读查询只承认在事务启动前就已经提交完成的数据对于读提交查询只承认在语句启动前就已经提交完成的数据 而当前读总是读取已经提交完成的最新版本。 你也可以想一下为什么表结构不支持“可重复读”这是因为表结构没有对应的行数据也没有 row trx_id因此只能遵循当前读的逻辑。 当然MySQL 8.0 已经可以把表结构放在 InnoDB 字典里了也许以后会支持表结构的可重复读。
http://www.yayakq.cn/news/2619/

相关文章:

  • 咸阳网站设计东莞市建设局网站
  • 加强网站建设管理办法wordpress 安全 插件下载失败
  • 前端开发做移动端的网站企业展厅设计图片欣赏
  • 重庆做网站电话中国建设招标网?官方网站
  • 河南网站建设广州自助网站制作
  • 微表单网站通过ip访问网站需要怎么做
  • 有哪些网站可以做笔译wordpress数据库损坏网站
  • 广东华电建设股份有限公司网站大芬网站建设
  • 提供哈尔滨网站建设服务wordpress 进管理页面
  • 网站被搜索引擎收录中铁建设集团有限公司门户登录门户
  • 档案网站建设视频做网站需要写代码吗
  • 网站欢迎页面模板下载wordpress建多个网站
  • 天津做网站报价一个网站包括
  • 网站域名如何备案信息wordpress 耗时
  • 宁波免费网站建站模板手机创建微信公众号
  • 西安网站建设公司排行榜网站开发用什么写得比较好
  • 网站建设平台seo网络优化平台
  • 备案网站建设书哈尔滨做网站的价格
  • 网站优化技巧做电影网站放抢先版
  • flash网站设计师怎样新建网站
  • 可以自己做网站服务器不网站备案更改
  • 教做详情页的网站wordpress小工具编辑
  • 持续推进网站建设php做网站难么
  • 成都彩票网站建设重庆市建设工程安全管理信息网
  • 和镜像网站做友链环保局网站建设
  • WordPress修改网站背景网站建设 php 企业网站
  • 网站企业备案资料长治怎么做平台软件
  • 信息网站模板广东建设信息网安全员查询
  • 游戏网站建设计划书网站灰色 代码
  • 长春网站制作费用2022年近期重大新闻事件