首页 数据库 mysql教程 mysql的mvcc多版本统制

mysql的mvcc多版本统制

Jun 07, 2016 pm 04:16 PM
mvcc mysql 版本

mysql的mvcc多版本控制 最近在看数据库的东西,了解到mysql的mvcc后,开始寻找各种资料,但说的都不是很清楚,看了几天,发现还是不知道是咋回事,今天找到一篇文章,讲的非常透彻,很清楚,拿出来记录在这里 ? Mysql到底是怎么实现MVCC的?这个问题无数人都

mysql的mvcc多版本控制

最近在看数据库的东西,了解到mysql的mvcc后,开始寻找各种资料,但说的都不是很清楚,看了几天,发现还是不知道是咋回事,今天找到一篇文章,讲的非常透彻,很清楚,拿出来记录在这里

?

Mysql到底是怎么实现MVCC的?这个问题无数人都在问,但google中并无答案,本文尝试从Mysql源码中寻找答案。

? 在Mysql中MVCC是在Innodb存储引擎中得到支持的,Innodb为每行记录都实现了三个隐藏字段:

?

  • 6字节的事务ID(DB_TRX_ID?
  • 7字节的回滚指针(DB_ROLL_PTR
  • 隐藏的ID
6字节的事物ID用来标识该行所述的事务,7字节的回滚指针需要了解下Innodb的事务模型。 ?

1. Innodb的事务相关概念

为了支持事务,Innbodb引入了下面几个概念:
  • redo log
    redo log就是保存执行的SQL语句到一个指定的Log文件,当Mysql执行recovery时重新执行redo log记录的SQL操作即可。当客户端执行每条SQL(更新语句)时,redo log会被首先写入log buffer;当客户端执行COMMIT命令时,log buffer中的内容会被视情况刷新到磁盘。redo log在磁盘上作为一个独立的文件存在,即Innodb的log文件。
  • undo log
    与redo log相反,undo log是为回滚而用,具体内容就是copy事务前的数据库内容(行)到undo buffer,在适合的时间把undo buffer中的内容刷新到磁盘。undo buffer与redo buffer一样,也是环形缓冲,但当缓冲满的时候,undo buffer中的内容会也会被刷新到磁盘;与redo log不同的是,磁盘上不存在单独的undo log文件,所有的undo log均存放在主ibd数据文件中(表空间),即使客户端设置了每表一个数据文件也是如此。
  • rollback segment
    回滚段这个概念来自Oracle的事物模型,在Innodb中,undo log被划分为多个段,具体某行的undo log就保存在某个段中,称为回滚段。可以认为undo log和回滚段是同一意思。

  • Innodb提供了基于行的锁,如果行的数量非常大,则在高并发下锁的数量也可能会比较大,据Innodb文档说,Innodb对锁进行了空间有效优化,即使并发量高也不会导致内存耗尽。
    对行的锁有分两种:排他锁、共享锁。共享锁针对对,排他锁针对写,完全等同读写锁的概念。如果某个事务在更新某行(排他锁),则其他事物无论是读还是写本行都必须等待;如果某个事物读某行(共享锁),则其他读的事物无需等待,而写事物则需等待。通过共享锁,保证了多读之间的无等待性,但是锁的应用又依赖Mysql的事务隔离级别。
  • 隔离级别
    隔离级别用来限制事务直接的交互程度,目前有几个工业标准:
    -?READ_UNCOMMITTED:脏读
    -?READ_COMMITTED:读提交
    -?REPEATABLE_READ:重复读
    -?SERIALIZABLE:串行化
    Innodb对四种类型都支持,脏读和串行化应用场景不多,读提交、重复读用的比较广泛,后面会介绍其实现方式。

2. 行的更新过程

下面演示下事务对某行记录的更新过程:

1. 初始数据行

F1~F6是某行列的名字,1~6是其对应的数据。后面三个隐含字段分别对应该行的事务号和回滚指针,假如这条数据是刚INSERT的,可以认为ID为1,其他两个字段为空。

2.事务1更改该行的各字段的值

当事务1更改该行的值时,会进行如下操作:
  • 用排他锁锁定该行
  • 记录redo log
  • 把该行修改前的值Copy到undo log,即上图中下面的行
  • 修改当前行的值,填写事务编号,使回滚指针指向undo log中的修改前的行

3.事务2修改该行的值

与事务1相同,此时undo log,中有有两行记录,并且通过回滚指针连在一起。 因此,如果undo log一直不删除,则会通过当前记录的回滚指针回溯到该行创建时的初始内容,所幸的时在Innodb中存在purge线程,它会查询那些比现在最老的活动事务还早的undo log,并删除它们,从而保证undo log文件不至于无限增长。

4. 事务提交

当事务正常提交时Innbod只需要更改事务状态为COMMIT即可,不需做其他额外的工作,而Rollback则稍微复杂点,需要根据当前回滚指针从undo log中找出事务修改前的版本,并恢复。如果事务影响的行非常多,回滚则可能会变的效率不高,根据经验值没事务行数在1000~10000之间,Innodb效率还是非常高的。很显然,Innodb是一个COMMIT效率比Rollback高的存储引擎。据说,Postgress的实现恰好与此相反。

5. Insert?Undo log

上述过程确切地说是描述了UPDATE的事务过程,其实undo log分insert和update undo log,因为insert时,原始的数据并不存在,所以回滚时把insert undo log丢弃即可,而update undo log则必须遵守上述过程。

3. 事务级别

众所周知地是更新(update、insert、delete)是一个事务过程,在Innodb中,查询也是一个事务,只读事务。当读写事务并发访问同一行数据时,能读到什么样的内容则依赖事务级别:
  • READ_UNCOMMITTED
    读未提交时,读事务直接读取主记录,无论更新事务是否完成
  • READ_COMMITTED
    读提交时,读事务每次都读取undo log中最近的版本,因此两次对同一字段的读可能读到不同的数据(幻读),但能保证每次都读到最新的数据。
  • REPEATABLE_READ
    每次都读取指定的版本,这样保证不会产生幻读,但可能读不到最新的数据
  • SERIALIZABLE
    锁表,读写相互阻塞,使用较少
读事务一般有SELECT语句触发,在Innodb中保证其非阻塞,但带FOR UPDATE的SELECT除外,带FOR UPDATE的SELECT会对行加排他锁,等待更新事务完成后读取其最新内容。就整个Innodb的设计目标来说,就是提供高效的、非阻塞的查询操作。

4. MVCC

上述更新前建立undo log,根据各种策略读取时非阻塞就是MVCC,undo log中的行就是MVCC中的多版本,这个可能与我们所理解的MVCC有较大的出入,一般我们认为MVCC有下面几个特点:
  • 每行数据都存在一个版本,每次数据更新时都更新该版本
  • 修改时Copy出当前版本随意修改,个事务之间无干扰
  • 保存时比较版本号,如果成功(commit),则覆盖原记录;失败则放弃copy(rollback)
就是每行都有版本号,保存时根据版本号决定是否成功,听起来含有乐观锁的味道。。。,而Innodb的实现方式是:
  • 事务以排他锁的形式修改原始数据
  • 把修改前的数据存放于undo log,通过回滚指针与主数据关联
  • 修改成功(commit)啥都不做,失败则恢复undo log中的数据(rollback)
二者最本质的区别是,当修改数据时是否要排他锁定,如果锁定了还算不算是MVCC?? ? Innodb的实现真算不上MVCC,因为并没有实现核心的多版本共存,undo log中的内容只是串行化的结果,记录了多个事务的过程,不属于多版本共存。但理想的MVCC是难以实现的,当事务仅修改一行记录使用理想的MVCC模式是没有问题的,可以通过比较版本号进行回滚;但当事务影响到多行数据时,理想的MVCC据无能为力了。 ? 比如,如果Transaciton1执行理想的MVCC,修改Row1成功,而修改Row2失败,此时需要回滚Row1,但因为Row1没有被锁定,其数据可能又被Transaction2所修改,如果此时回滚Row1的内容,则会破坏Transaction2的修改结果,导致Transaction2违反ACID。 ? 理想MVCC难以实现的根本原因在于企图通过乐观锁代替二段提交。修改两行数据,但为了保证其一致性,与修改两个分布式系统中的数据并无区别,而二提交是目前这种场景保证一致性的唯一手段。二段提交的本质是锁定,乐观锁的本质是消除锁定,二者矛盾,故理想的MVCC难以真正在实际中被应用,Innodb只是借了MVCC这个名字,提供了读的非阻塞而已。

5.总结

也不是说MVCC就无处可用,对一些一致性要求不高的场景和对单一数据的操作的场景还是可以发挥作用的,比如多个事务同时更改用户在线数,如果某个事务更新失败则重新计算后重试,直至成功。这样使用MVCC会极大地提高并发数,并消除线程锁。 ? 引自:http://blog.csdn.net/chen77716/article/details/6742128
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

MySQL:世界上最受欢迎的数据库的简介 MySQL:世界上最受欢迎的数据库的简介 Apr 12, 2025 am 12:18 AM

MySQL是一种开源的关系型数据库管理系统,主要用于快速、可靠地存储和检索数据。其工作原理包括客户端请求、查询解析、执行查询和返回结果。使用示例包括创建表、插入和查询数据,以及高级功能如JOIN操作。常见错误涉及SQL语法、数据类型和权限问题,优化建议包括使用索引、优化查询和分表分区。

MySQL的位置:数据库和编程 MySQL的位置:数据库和编程 Apr 13, 2025 am 12:18 AM

MySQL在数据库和编程中的地位非常重要,它是一个开源的关系型数据库管理系统,广泛应用于各种应用场景。1)MySQL提供高效的数据存储、组织和检索功能,支持Web、移动和企业级系统。2)它使用客户端-服务器架构,支持多种存储引擎和索引优化。3)基本用法包括创建表和插入数据,高级用法涉及多表JOIN和复杂查询。4)常见问题如SQL语法错误和性能问题可以通过EXPLAIN命令和慢查询日志调试。5)性能优化方法包括合理使用索引、优化查询和使用缓存,最佳实践包括使用事务和PreparedStatemen

apache怎么连接数据库 apache怎么连接数据库 Apr 13, 2025 pm 01:03 PM

Apache 连接数据库需要以下步骤:安装数据库驱动程序。配置 web.xml 文件以创建连接池。创建 JDBC 数据源,指定连接设置。从 Java 代码中使用 JDBC API 访问数据库,包括获取连接、创建语句、绑定参数、执行查询或更新以及处理结果。

为什么要使用mysql?利益和优势 为什么要使用mysql?利益和优势 Apr 12, 2025 am 12:17 AM

选择MySQL的原因是其性能、可靠性、易用性和社区支持。1.MySQL提供高效的数据存储和检索功能,支持多种数据类型和高级查询操作。2.采用客户端-服务器架构和多种存储引擎,支持事务和查询优化。3.易于使用,支持多种操作系统和编程语言。4.拥有强大的社区支持,提供丰富的资源和解决方案。

docker怎么启动mysql docker怎么启动mysql Apr 15, 2025 pm 12:09 PM

在 Docker 中启动 MySQL 的过程包含以下步骤:拉取 MySQL 镜像创建并启动容器,设置根用户密码并映射端口验证连接创建数据库和用户授予对数据库的所有权限

MySQL的角色:Web应用程序中的数据库 MySQL的角色:Web应用程序中的数据库 Apr 17, 2025 am 12:23 AM

MySQL在Web应用中的主要作用是存储和管理数据。1.MySQL高效处理用户信息、产品目录和交易记录等数据。2.通过SQL查询,开发者能从数据库提取信息生成动态内容。3.MySQL基于客户端-服务器模型工作,确保查询速度可接受。

laravel入门实例 laravel入门实例 Apr 18, 2025 pm 12:45 PM

Laravel 是一款 PHP 框架,用于轻松构建 Web 应用程序。它提供一系列强大的功能,包括:安装: 使用 Composer 全局安装 Laravel CLI,并在项目目录中创建应用程序。路由: 在 routes/web.php 中定义 URL 和处理函数之间的关系。视图: 在 resources/views 中创建视图以呈现应用程序的界面。数据库集成: 提供与 MySQL 等数据库的开箱即用集成,并使用迁移来创建和修改表。模型和控制器: 模型表示数据库实体,控制器处理 HTTP 请求。

centos7如何安装mysql centos7如何安装mysql Apr 14, 2025 pm 08:30 PM

优雅安装 MySQL 的关键在于添加 MySQL 官方仓库。具体步骤如下:下载 MySQL 官方 GPG 密钥,防止钓鱼攻击。添加 MySQL 仓库文件:rpm -Uvh https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm更新 yum 仓库缓存:yum update安装 MySQL:yum install mysql-server启动 MySQL 服务:systemctl start mysqld设置开机自启动

See all articles