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

校园网站开发技术网站顶部代码

校园网站开发技术,网站顶部代码,有没有可以做app的网站,班级优化大师怎么用目录 从一个例子说起 快照读和当前读 事务的启动时机和读视图生成的时刻 MVCC 隐藏字段 Undo Log回滚日志 Read View - 读视图 可重复读(RC)隔离级别下的MVCC 读提交(RR)隔离级别下的MCC 关于MVCC的一些疑问 1.为什么需要 MVCC #xff1f;如果没有 MVCC 会怎样如果没有 MVCC 会怎样 2.多版本是在索引保存了该行数据的多个版本吗 总结 从一个例子说起 当数据库上有多个事务同时执行的时候就可能出现脏读dirty read、不可重复读non-repeatable read、幻读phantom read的问题为了解决这些问题就有了“隔离级别”的概念。 MySQL有4个隔离级别 读未提交:一个事务还没提交时它做的变更就能被别的事务看到。读提交:一个事务提交之后它做的变更才会被其他事务看到。可重复读:一个事务执行过程中看到的数据总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下未提交变更对其他事务也是不可见的。串行化顾名思义是对于同一行记录“写”会加“写锁”“读”会加“读锁”。当出现读写锁冲突的时候后访问的事务必须等前一个事务执行完成才能继续执行。 用一个例子说明这几种隔离级别。假设数据表 T 中只有一列其中一行的值为 1下面是按照时间顺序执行两个事务的行为。 mysql create table T(c int) engineInnoDB; insert into T(c) values(1); 在不同的隔离级别中事务 A 会有不同的返回结果也就是图里面 V1、V2、V3 的返回值会不同。 隔离级别是“读未提交” 则 V1 的值就是 2。这时候事务 B 虽然还没有提交但是结果已经被 A 看到了。因此V2、V3 也都是 2。隔离级别是“读提交”则 V1 是 1V2 的值是 2。事务 B 的更新在提交后才能被 A 看到。所以V1还是1而 V3 的值是 2。隔离级别是“可重复读”则 V1、V2 是 1V3 是 2。之所以 V2 还是 1遵循的就是这个要求事务在执行期间看到的数据前后必须是一致的。隔离级别是“串行化”则在事务 B 执行“将 1 改成 2”的时候会被锁住。直到事务 A 提交后事务 B 才可以继续执行。所以从 A 的角度看 V1、V2 值是 1V3 的值是 2。 在实现上数据库里面会创建一个视图read-view访问的时候以视图的逻辑结果为准。在“可重复读”隔离级别下这个视图是在事务启动时创建的整个事务存在期间都用这个视图。在“读提交”隔离级别下这个视图是在每个 SQL 语句开始执行的时候创建的。 这里需要先讲解下当前读和快照读 和 事务的启动时机和读视图生成的时刻 快照读和当前读 MySQL读取数据实际上有两种模式分别是当前读和快照读。 快照读普通的select语句(即是不加锁的select操作) 都是采用 快照读的模式。 当前读数据修改的操作(update、insert、delete) 和select ... lock in share mode; select ... for update;都是采用 当前读的模式对读取到的数据(索引记录)加锁来保证数据一致性是读到最新的数据。 事务的启动时机和读视图生成的时刻 在 MySQL 有两种开启事务的命令分别是 第一种begin/start transaction 命令第二种start transaction with consistent snapshot 命令 begin/start transaction 命令并不是一个事务的起点在执行到它们之后的第一个操作 InnoDB 表的语句事务才真正启动。如果你想要马上启动一个事务可以使用 start transaction with consistent snapshot 这个命令。 第一种启动方式一致性视图是在执行第一个快照读语句时创建的 第二种启动方式一致性视图是在执行start transaction with consistent snapshot 时创建的。 说到视图read-view那就会引出MVCC。而事务隔离就是通过MVCC来实现的。 更加准确来说实现事务隔离的方法是有两种 针对快照读普通 select 语句是通过 MVCC 方式解决了幻读因为可重复读隔离级别下事务执行过程中看到的数据一直跟这个事务启动时看到的数据是一致的即使中途有其他事务插入了一条数据是查询不出来这条数据的所以就很好了避免幻读问题。针对当前读select ... for update 等语句是通过 next-key lock记录锁间隙锁方式解决了幻读因为当执行 select ... for update 语句的时候会加上 next-key lock如果有其他事务在 next-key lock 锁范围内插入了一条记录那么这个插入语句就会被阻塞无法成功插入所以就很好了避免幻读问题。 所以事务隔离是通过MVCC 和 加锁 实现的。 那么MVCC 用来实现哪几个隔离级别 隔离级别如果是读未提交的话直接读最新版本的数据就行了根本就不需要保存以前的版本即是“读未提交”隔离没有视图概念。可串行化隔离级别事务都串行执行了(就是直接加锁避免并行访问所以也不需要多版本。因此 MVCC 是用来实现读已提交和可重复读。 MVCC 多版本并发控制(Multi-Version  Concurrency Control)是一种用来解决读-写冲突的无锁并发控制可以做到在读操作时不用阻塞写操作写操作也不用阻塞读操作提高了数据库并发读写的性能。 最早的数据库系统只有读读之间可以并发读写写读写写都要阻塞。引入多版本之后只有写写之间相互阻塞其他三种操作都可以并行这样大幅度提高了 InnoDB 的并发度。 实现原理主要是依赖记录中的 三个隐藏字段undo日志 Read View 来实现的。 隐藏字段 innodb引擎保存的行数据是有三个隐藏字段的。 具体的内容可以查看该文章MySQL的一行数据是如何存储的  innodb引擎表 的聚簇索引保存的数据就是完整的行数据(即是上图的数据。这里就主要是使用TRX_ID和ROLL_PTR。 DB_TRX_ID 最近修改事务ID记录插入这条记录或最后一次修改该记录的事务ID。 DB_ROLL_PTR 回滚指针指向这条记录的上一个版本即是指向指向 undo log 的指针。用于配合Undo Log指向上一个版本。 每次对某条聚簇索引记录进行改动时都会把旧版本的记录写入到 undo 日志中。DB_ROLL_PTR是个指针指向每一个旧版本记录于是就可以通过它找到修改前的记录。 Undo Log回滚日志 这个是在增、改、删操作的时候产生的便于数据回滚的日志。当INSERT操作的时候产生的回滚日志在事务提交后可被立即删除。而UPDATE和DELETE操作的时候产生的Undo Log日志不仅在进行数据回滚时需要在进行快照读时也需要所以不会立即被删除。因为undo log 记录事务修改之前版本的数据信息因此假如由于系统错误或者rollback操作而回滚的话可以根据undo log的信息来进行回滚到没被修改前的状态。 undo log 版本链  用一个表做例子 建表语句如下。 mysql CREATE TABLE t (id int NOT NULL,age int DEFAULT NULL,name varchar(10) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB; 上图中的(1): 从图中可以得知此时插入的事务ID是1此时插入会同时生成一条 undo log 并且行记录上的 roll_pointer 会指向这条 undo log 而这条 undo log的类型是TRX_UNDO_INSERT_REC代表是 insert 生成的里面还存储了主键值(还有其他值这里就不做过多介绍)。 所以 InnoDB 可以根据 undo log 里的主键的值找到这条记录然后删除该主键对应的行数据来实现回滚的效果。因此可以简单地理解 undolog 里面存储的就是当前操作的反向操作认为里面存了个delete 30即可。 上图中的(2): ​此时事务1提交然后另一个事务ID为 2的事务执行 update t set age3 where id30 此时的行记录和 undolog 就如上图所示的(2)。 之前 insert 产生的 undo log没了insert 的事务提交了之后对应的 undolog 就被回收了为什么呢 因为不可能有别的事务会访问比这还要早的版本了访问插入之前的版本插入之前的版本都没有这行数据要如何访问??没得访问的。所以insert事务提交后对应的undo log就回收了。 (看到很多文章写的是insert对其他事务不可见只对本事务可见所以提交后就可删除感觉这理由是不妥的 update 产生的 undolog其类型为 TRX_UNDO_UPD_EXIST_REC并且记录上一版本的trx_id和数据。 上图中的(3): 此时事务 2提交然后另一个 ID 为 3 的事务执行update t set namea3 where id30此时的记录和 undolog 就如上图所示中的(3)。 update 产生的 undolog 不会马上删除因为可能有别的事务需要访问之前的版本所以不能删。这样就串成了一个版本链可以看到该记录本身加上两条 undo log这条 id 为 30的记录就共有三个版本。 不同事务或相同事务对同一条记录进行修改会导致该记录的undolog生成一条记录版本链表链表的头部是最新的记录链表尾部是最早的记录。我们把这个链表称之为 版本链。 Read View - 读视图 Read View就是事务进行快照读操作的时候生产的读视图(Read View)在该事务执行的快照读的那一刻(select ....)会生成数据库系统当前的一个快照记录并维护系统当前活跃事务的ID(当每个事务开启时都会被分配一个ID, 这个ID是递增的所以最新的事务ID值越大)。 已经弄清楚版本链后而 readView 就是用来判断哪个版本对当前事务可见的。 readView中有4个概念 m_ids 指的是在创建 Read View 时当前数据库中「活跃事务」的事务 id 列表注意是一个列表“活跃事务”指的就是启动了但还没提交的事务。min_trx_id 指的是在创建 Read View 时当前数据库中「活跃事务」中事务 id 最小的事务也就是 m_ids 的最小值。max_trx_id 这个并不是 m_ids 的最大值而是创建 Read View 时当前数据库中应该给下一个事务的 id 值也就是全局事务中最大的事务 id 值 1creator_trx_id 指的是创建该 Read View 的事务的事务 id。 知道版本链和读视图后那如何通过读视图来判断哪个版本对当前事务是可见的呢 代码中判断的逻辑如下 从最新版本开始沿着版本链逐渐寻找老的版本如果遇到符合任一条件的版本就返回。 注意在不同的隔离级别下快照读生成的ReadView规则不同 read committed (读已提交)事务每次select时创建ReadViewrepeatable read (可重复读)事务第一次select时创建ReadView后续一直使用 而我们写sql语句后进行分析可见版本是看不到min_trx_id和max_trx_id这些数据的。那我们用另一种方式来判断。 不知min_trx_id等数据的分析规则 一个数据版本对于一个事务视图来说除了自己的更新总是可见以外有三种情况 版本未提交不可见版本已提交但是是在视图创建后提交的不可见版本已提交而且是在视图创建前提交的可见。 这种通过 版本链 来控制并发事务访问同一个记录时的行为就叫 MVCC多版本并发控制。 可重复读(RC)隔离级别下的MVCC 用一个表做例子 建表和初始化语句如下。 mysql CREATE TABLE t (id int NOT NULL,age int DEFAULT NULL,name varchar(10) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB; insert into t values(30,30,a30); 从上图时间顺序事务2先启动跟着是事务3,4,5依次启动。事务2对应的事务id是2依次类推。 因为是RC隔离级别所以每次select都会生成新的快照。 下面是每次提交事务生成的版本链第一次快照读的ReadView 只分析事务5中的select从最新版本开始沿着版本链逐渐寻找老的版本。 第一次select: 当前最新版本的事务id是4所以trx_id为4不等于create_trx_id所以不符合条件①。条件②,③,④也都不符合。所以事务id是4的版本不可见。跟着是老版本,事务id为3的版本条件①不符合条件②(33不符合不符合。条件③(36),说明可能可以可见条件④3在[3,4,5]范围内说明该版本在活跃事务列表中未提交不可见。所以事务id是3的版本不可见。事务id是2的版本trx_id2。条件①不符合条件②符合(23)。所以事务id2的版本可见。 查看上图的并发执行过程对比事务5发现事务2是已提交因此此刻可以读取事务2提交过的数据。 第二次select也是这样分析但注意的是在RC隔离级别下是生成新的读视图的这里还是按照上面的逻辑分析的这里就不具体写了留给读者分析。 用不知min_trx_id等数据的分析规则进行分析 第一次select: 从最新版本开始查看最新版本是事务id为4的还没提交属于情况1不可见。到事务id为3的版本还未提交属于情况1不可见。到事务id为2的版本该版本已提交而且是在视图创建前提交的(即是在事务5创建视图前,属于情况3,所以事务id为2的版本可见。 第二次select: 从最新版本开始查看最新版本是事务id为4的还没提交属于情况1不可见。到事务id为3的版本已提交并且在视图创建前提交的(即是在事务创建视图前第二次select属于情况3所以事务id为3的版本可见。 读提交(RR)隔离级别下的MCC 这里的事务执行顺序和RC隔离级别的是一样的。 在RR隔离级别下只是在事务中第一次快照读时生成ReadView后续都是复用该 ReadView那么既然ReadView都一样 ReadView的版本链匹配规则也一样 那么最终快照读返 回的结果也是一样的。而且都是和RC隔离级别第一次select中的结果一样的。分析过程和RC级别的一样。 用不知min_trx_id等数据的分析规则进行分析 第一次select:和RC隔离级别的第一次select是一样的事务id是2的版本可见。 第二次select: 从最新版本开始查看最新版本是事务id为4的还没提交属于情况1不可见。到事务id为3的版本已提交但是是在视图创建后提交的(即是在事务5创建视图前因为RR级别是延用第一次生成的视图属于情况2不可见。到事务id为2的版本该版本已提交而且是在视图创建前提交的(即是在事务5创建视图前,属于情况3,所以事务id为2的版本可见。 这样分析第一次select和第一次select读取的数据是一致的。 关于MVCC的一些疑问  1.为什么需要 MVCC 如果没有 MVCC 会怎样 如果没有MVCC读写操作之间会有冲突。 假设一个场景 事务A在执行中此时事务B修改了记录1还没提交而此时事务A想要读取记录1。事务B还没提交所以事务A无法提取到最新的记录1,不然就是脏读了。 那么事务A就是应该读取被事务B修改前的记录。但是记录1已被事务B修改了那就只能用锁用锁阻塞等到事务B的提交。这种实现就是基于锁的并发控制 Lock Based Concurrency ControlLBCC)。 这时如果有多版本就好了保存事务B修改记录1之前的版本数据。此时事务A就可以读取之前版本的数据这样读写操作就不会阻塞,也不用加锁。所以说 MVCC 提高了事务的并发度提升数据库的性能。 2.多版本是在索引保存了该行数据的多个版本吗 这个多版本说法只是为了便于理解或者说展现出来像多版本的样子而已。 InnoDB 不会真的存储多个版本的数据只是借助 undo log 记录每次写操作的反向操作所以索引上对应的记录只会有一个版本(即最新版本)。只不过可以根据 undo log 中的记录反向操作得到数据的历史版本所以看起来是多个版本。 总结 事务是在 MySQL 引擎层实现的默认的 InnoDB 引擎支持事务。 MySQL InnoDB 引擎的默认隔离级别是 可重复读(RR)但不建议将隔离级别升级为串行化因为这会导致数据库并发时性能很差。RR隔离级别是可以很大程度避免幻读现象并不是完全解决解决的方案有两种 针对快照读普通 select 语句是通过 MVCC 方式解决了幻读因为可重复读隔离级别下事务执行过程中看到的数据一直跟这个事务启动时看到的数据是一致的即使中途有其他事务插入了一条数据是查询不出来这条数据的所以就很好了避免幻读问题。针对当前读select ... for update 等语句是通过 next-key lock记录锁间隙锁方式解决了幻读因为当执行 select ... for update 语句的时候会加上 next-key lock如果有其他事务在 next-key lock 锁范围内插入了一条记录那么这个插入语句就会被阻塞无法成功插入所以就很好了避免幻读问题。 所以事务隔离是通过MVCC 和 加锁 实现的。
http://www.dnsts.com.cn/news/55466.html

相关文章:

  • 流浪动物网站开发影视公司招聘信息
  • 如何申请开通网站专做耐克阿迪鞋网站
  • 国家建设局网站河北seo基础知识
  • 建设部网站查不到注册证怎么回事设置网关
  • 网站维护需要什么技能保定八大平台公司
  • 企业网站建设的必要性网站建设伍金手指下拉2
  • 手机网站开发模拟手机做网站链接的页面怎么做
  • 青岛做网站公司电话项目管理证书 pmp
  • 美食网站html模板网站收录查询
  • 金湖企业网站制作贵阳住房和城乡建设部网站
  • 织梦网站后台网址手机如何强制下载网页视频
  • 佛山房地产网站建设好用的做网站的app
  • 网站的图文链接怎么做it公司做网站用什么软件
  • 郑州做网站公司yooker怎么做qq可信任网站
  • 项目定制开发网站淘客软件自动做网站
  • 系统下载网站建设模板莒南县建设局网站
  • 站长统计app网络建站 响应式网站
  • 上海建设银行网站静安支行中国建行个人登录入口
  • 深圳 旅游 网站建设购物网站开发教学视频
  • 网站推广由什么样的人来做服装网站设计理念
  • 福永招聘网站建设做方案收集图片的网站
  • 企业网站微信建设网站被黑
  • html5网站建设基本流程图网站开发为什么要用框架
  • 海阳网网站电商网络推广是什么
  • 可以直接玩游戏的网站seo优化神器
  • php网站建设入门教程外贸开发网站建设
  • 网站推广广告语网站建设的软硬件平台
  • 邢台规划局网站建设seo兼职论坛
  • 个人合法网站怎么做石景山网站建设设计公司
  • 昆明汽车建站网站模板网红营销英文