MYSQL数据库Innodb 引擎mvcc锁实现原理

目录
  • 1 数据库设置隔离级别
  • 2 数据库表以及案例操作
  • 3 mvcc 实现原理
  • 4 ACID 的实现

前言:

大家都知道在java 开发过程中,会经常用到锁,在java 代码中,我们都知道锁是加在对象头上的,在java对象布局中有锁的标志位。程序通过判断锁的标志位来获取加锁的情况。但是在mysql 中,锁的实现原理是什么呢。可能大家都听过 mvcc,但是mvcc 的实现原理是什么呢,可能就说不太清楚了,本文就以实例说明来mvcc 的实现原理。

1 数据库设置隔离级别

我们都知道数据库的隔离级别可以分为以下:

  • 读未提交 RU : read uncommitted
  • 读提交   RC : read committed
  • 可重复读 RR : repeatable read 默认隔离级别
  • 序列化   SE : serializable 序列化

我们使用select @@transaction_isolation;来查看数据库的隔离级别,可能有读者会有疑问了,不是应该是select @@tx_isolation;吗, 因为我的电脑上装的是 mysql 8.0, 之前的 tx 也是 transaction的简写,高版本的mysql 已经使用 transaction 了。

# 查询当前会话隔离级别
select @@transaction_isolation;
# 查看当前系统的隔离级别
select @@global.transaction_isolation;
# 命令行开启事务,区别在于前者是第一条语句的执行时间点为事务开始的时间点,建立一致性读,后者是立即建立一致性读,开始执行事务
start transaction 或者 start transaction with consistent snapshot
# 设置数据库隔离级别,如若设置会话级别,则修改 global 为session 即可
set global transaction isolation level REPEATABLE READ;
set global transaction isolation level READ COMMITTED;
set global transaction isolation level READ UNCOMMITTED;
set global transaction isolation level SERIALIZABLE;

2 数据库表以及案例操作

操作的数据库表为:

CREATE TABLE `t_user` (
  `id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
  `age` int DEFAULT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';
# 初始化语句
INSERT INTO `t_user`(`id`, `age`) VALUES (1, 3);
# 使用的操作语句
select * from t_user where id = 1;
update t_user set age = age + 1  where id = 1;

案例如图所示:

sessionA,sessionB,sessionC 是连接数据库的3个会话窗口,mysql 数据库的默认隔离级别为RR,为了达到效果我们把当前的数据库隔离级别改为RC,语句如下:

set session transaction isolation level READ COMMITTED;

setp1 准备工作,设置当前会话事务隔离级别,查看数据库表中的数据。窗口从左往右依次是sessionA、sessinB和sessionC。

setp2 t1 时刻,sessionA 和 sessionB 开启事务。sessionA t2 时刻执行查询语句,sessionC 执行更新操作,可以看到此时 sessionC 立马执行成功。

step3 t3 时刻,sessionB 查询最新的数据,并执行更新操作

step4 t4 时刻,sessionA 查询最新数据,并在t5 时刻更新数据,这里因为sessionB 的事务还未结束,因此执行的操作会阻塞到超时(这里刻意等待到超时),t6 时刻sessionB 查询数据,并提交事务。

step5 sesionB 提交事务后,sessionA 重新执行语句,可以看到执行后的结果,然后提交事务。

通过上述的操作案例,我们可以观察到:

  • 在一个事务中的数据更改对本事务是可见的,此外的事务是否可见取决于其隔离级别。
  • 两个事务操作同一条数据,会造成等待。innodb 引擎默认开启死锁检测,并会设置锁的超时时间。
# 设置超时时间默认是50s
innodb_lock_wait_timeout
# 开启死锁检测,默认是开启死锁检测,默认值为 on,开启死锁检测
innodb_deadlock_detect
# 查看更多innodb 引擎的配置
show variables like '%innodb%'
  • 在会话中进行数据修改,默认事务是自动提交的。

3 mvcc 实现原理

mvcc,Multi-Version Concurrency Control,即版本并发访问控制,是 mysql innodb 引擎实现的一种并发访问控制方法,用于其事务的实现。其主要作用是为了提高数据库的并发性能,更好地处理读写冲突问题,在遇到冲突的境况也能够做到不加锁,非阻塞并发读取数据。 在解释实现原理前,先了解一下当前读和快照读。

  • 当前读:像更改数据的操作(update/delete/insert)操作还有共享锁和排他锁(lock in share mode和for update)这操作都需要读取当前最新版本的数据,否则就会有更新丢失的情况。数据库的修改操作也是将数据所在的数据页从磁盘加载到内存,然后进行修改,最后写回到磁盘中。
  • 快照读:不加锁的select获取数据就是读快照,不会产生阻塞。在串行化的数据库隔离级别下,快照读会退化成当前度。每行数据都有多个版本,当前读就是获取最新的已经提交过得版本数据。

接下来讲述的是非常重要的部分:

  • 已经提交的事务
  • 未被提交的事务
  • 未开始的事务

在可重复读的隔离级别下,事务启动需要对整个库做备份,这显然是不可能的,实际上mvcc也没有这样做,而是利用版本号来控制,也就是事务开始时向 innodb 事务系统申请一个 transaction id,这个id申请顺序是严格递增的。每行数据的版本号 row trx_id = transaction id , 也就可以保证其版本的唯一性。可以保证事务启动时,会获取当前所有活跃事务id的数组,可以保证其唯一性。事务id数组中的最小的id记为低水位,数组中的最大id+1记为高水位。低水位和高水位便是已经提交的事务-未提交的数据、未提交的事务-未开始的事务的分界标志位,以上就组成了当前事务的一致性视图(read-view)。

前面已经提到了,所有的数据都是有版本的,这个版本即row trx_id。当需要读快照时,就需要读取trx_id小于低水位且最大的trx_id版本号的数据。读当前就是读取当前最新版本的数据,如果数据正在事务的处理中,那么久需要等待,这也是为什么会出现锁等待超时的情况。

当在RC的数据库隔离级别下,每次的操作都会重新获取当前活跃的trx_id数组,形成新的一致性视图,这就是sessionB 在t3 时刻读取到了sessionC 在t2时刻提交的数据,因为在新的一致性视图中,sessionC 的trx_id 已经已经提交的事务了,所以就可以读取到。在sessionA 的t5 时刻,拿到的一致性视图中活跃的trx_id 数组中包含 sessionB 的活跃id,因为在更新数据时,需要当前读,而数据已经被锁住,所以出现了锁超时的情况。

而在RR的数据库隔离级别下,在事务开始时生成一个一致性视图,此后在事务提交之前,其 trx_id 数组不会发生变化,这样才能保证其可重复读的特性。RR相对于RC实现简单,区别在于是否在执行语句前更新一致性视图,活跃事务id的数组是否更新。

综上,我们就知道了mvcc 是如何实现可重复读和读提交的隔离级别了。

4 ACID 的实现

  • 事务的原子性 A 是通过 undolog 回滚日志来实现。
  • 事务的持久性 C 性是通过 redolog 重做日志来实现的。
  • 事务的隔离性 I 是通过 MVCC 来实现的。
  • 原子性,持久性,隔离性都实现了,那么一致性 D 也就实现了。

redo log 是mysql innodb 引擎产生的物理日志,其大小有一定的限制,采用循环写入的方式,写满之后进行刷盘。主要用于宕机后的数据恢复。redo log是一个循环写入的日志,可以理解为一个环,有 checkpoint 和 write pos 两个标志点,checkpoint之前的空间是清除后的可写空间,清除之前会更新到磁盘中,write pos是数据写入的位置,当两个标志点相遇表明redo log已经满了,这时数据库停止进行数据库更新语句的执行,转而进行redo log日志同步到磁盘中。

binlog 是mysql server 层记录逻辑的日志,可以一致追加写入,主要用于主从数据同步。

到此这篇关于MYSQL数据库Innodb 引擎mvcc锁实现原理的文章就介绍到这了,更多相关mysql mvcc锁实现内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • MySQL创建数据表时设定引擎MyISAM/InnoDB操作

    我在配置mysql时将配置文件中的默认存储引擎设定为了InnoDB.今天查看了MyISAM与InnoDB的区别,在该文中的第七条"MyISAM支持GIS数据,InnoDB不支持.即MyISAM支持以下空间数据对象:Point,Line,Polygon,Surface等." 作为一个地理信息系统专业的学生(其实是测绘专业)来讲,能存储空间数据的数据库才是好数据库,原谅我是数据库小白的身份. 有三种方式可以设定数据库引擎: (1)修改配置文件 将安装目录下~\MySQL\mysql-5.6

  • MySQL中的乐观锁,悲观锁和MVCC全面解析

    前言 在数据库的实际使用过程中,我们常常会遇到不希望数据被同时写或者读的情景,例如秒杀场景下,两个请求同时读到系统还有库存1个,然后又先后把库存更新为0,这时候就会出现超卖的情况,这时候货物的实际库存和我们的记录就会对应不上了. 为了解决这种资源竞争导致的数据不一致等问题,我们需要有一种机制来进行保证数据的正确访问和修改,而在数据库中,这种机制就是数据库的并发控制.其中乐观并发控制,悲观并发控制和多版本并发控制是数据库并发控制主要采用的技术手段. 悲观并发控制 本质 维基百科:在关系数据库管理系

  • 详解MySql中InnoDB存储引擎中的各种锁

    目录 什么是锁 InnoDB存储引擎中的锁 锁的算法 行锁的3种算法 幻像问题 锁的问题 脏读 不可重复读 丢失更新 死锁 什么是锁 现实生活中的锁是为了保护你的私有物品,在数据库中锁是为了解决资源争抢的问题,锁是数据库系统区别于文件系统的一个关键特性.锁机制用于管理对共享资源的并发访. 数据库系统使用锁是为了支持对共享资源进行并发访问,提供数据的完整性和一致性 InnoDB存储引擎区别于MyISAM的两个重要特征就是:InnoDB存储引擎支持事务和行级别的锁,MyISAM只支持表级别的锁 In

  • MySQL存储引擎MyISAM与InnoDB区别总结整理

    1.MySQL默认存储引擎的变迁 在MySQL 5.1之前的版本中,默认的搜索引擎是MyISAM,从MySQL 5.5之后的版本中,默认的搜索引擎变更为InnoDB. 2.MyISAM与InnoDB存储引擎的主要特点 MyISAM存储引擎的特点是:表级锁.不支持事务和全文索引,适合一些CMS内容管理系统作为后台数据库使用,但是使用大并发.重负荷生产系统上,表锁结构的特性就显得力不从心: 以下是MySQL 5.7 MyISAM存储引擎的版本特性: InnoDB存储引擎的特点是:行级锁.事务安全(A

  • MySQL的存储引擎InnoDB和MyISAM

    目录 1.MyISAM底层存储 1.1MyISAM底层存储(非聚集索引方式) 1.2InnoDB底层存储(聚集索引方式) 2.InnoDB与MyISAM简介 3.MyISAM与InnoDB的比较 4.什么时候用MyISAM数据存储引擎?什么时候用InnoDB数据存储引擎? 1.MyISAM底层存储 (非聚集索引方式)与InnoDB底层存储(聚集索引方式) 1.1MyISAM底层存储(非聚集索引方式) Myisam 创建表后生成的文件有三个: frm:创建表的语句 MYD:表里面的数据文件(myi

  • MySQL的InnoDB存储引擎的数据页结构详解

    目录 1InnoDB页的概念 2数据页的结构 3记录在页中的存储 4PageDirectory页目录 5FileHeader文件头部 6InnoDB页和记录的关系 7没有索引时查找记录 总结 1 InnoDB页的概念 InnoDB是一个将表中的数据存储在磁盘上的存储引擎,即使我们关闭并重启服务器,数据还是存在.而真正处理数据的过程发生在内存中,所以需要把磁盘中的数据加载到内存中,所以需要把磁盘中的数据加载到内存中.如果处理写入和修改请求,还需要将内存中的内容刷新到磁盘上.而我们知道读写磁盘的速度

  • 关于Mysql隔离级别、锁与MVCC介绍

    本文意在弄清楚这些概念间的关系及其作用.弄清Mysql在开启事务的情况下,每条sql执行时的加锁操作和MVCC版本控制.为使讨论简单,本文忽略了GAP锁(间隙锁.范围锁). 我们经常所高并发,高可用.就是从质和量来评估,任何事物都可以从这两个角度来分析.在Mysql数据库中,事务就是用来保证质的,MVCC就是用来保证量的. 事务 我们使用事务来保证每一条SQL语句的结果执行符合我们的预期.我们说事务必须具备ACID特性.ACID中的三者:原子性.一致性和持久性其实描述的都差不多,保证SQL执行结

  • 详解MySQL InnoDB存储引擎的内存管理

    存储引擎之内存管理 在InnoDB存储引擎中,数据库中的缓冲池是通过LRU(Latest Recent Used,最近最少使用)算法来进行管理的,即最频繁使用的页在LRU列表的最前段,而最少使用的页在LRU列表的尾端,当缓冲池不能存放新读取到的页时,首先释放LRU列表尾端的页. 上面的图中,我使用8个数据页来表示队列,具体作用,先卖个关子.在InnoDB存储引擎中,缓冲池中页的默认大小是16KB,LRU列表中有一个midpoint的位置,新读取到的数据页并不是直接放入到LRU列表的首部,而是放入

  • MYSQL数据库Innodb 引擎mvcc锁实现原理

    目录 1 数据库设置隔离级别 2 数据库表以及案例操作 3 mvcc 实现原理 4 ACID 的实现 前言: 大家都知道在java 开发过程中,会经常用到锁,在java 代码中,我们都知道锁是加在对象头上的,在java对象布局中有锁的标志位.程序通过判断锁的标志位来获取加锁的情况.但是在mysql 中,锁的实现原理是什么呢.可能大家都听过 mvcc,但是mvcc 的实现原理是什么呢,可能就说不太清楚了,本文就以实例说明来mvcc 的实现原理. 1 数据库设置隔离级别 我们都知道数据库的隔离级别可

  • MySQL数据库InnoDB引擎下服务器断电数据恢复方法

    说明: 线上的一台MySQL数据库服务器突然断电,造成系统故障无法启动,重新安装系统后,找到之前的MySQL数据库文件夹. 问题: 通过复制文件的方式对之前的MySQL数据库进行恢复,发现在程序调用时找不到数据库中的表,造成网站无法正常访问. 分析: 1.MySQL数据库,使用拷贝文件方式来恢复数据库,只支持MyISAM引擎: 2.如果有数据库或数据表使用了InnoDB引擎,恢复的时候,必须连同MySQL数据库目录下的ibdata1文件一起拷贝过来. 解决办法: 1.停止MySQL服务 serv

  • MySQL数据库InnoDB引擎主从复制同步经验总结

    近期将公司的MySQL架构升级了,由原先的一主多从换成了DRBD+Heartbeat双主多从,正好手上有一个电子商务网站新项目也要上线了,用的是DRBD+Heartbeat双主一从,由于此过程还是有别于以前的MyISAM引擎的,所以这里也将其心得归纳总结了一下: 1)MySQL的replication过程是一个异步同步的过程,并非完全的主从同步,所以同步的过程中是有延迟的,如果做了读写分离的业务的话,建议也要监控此延迟时间: 2)MySQL的master与slave机器记得server-id要保

  • MySQL数据库InnoDB数据恢复工具的使用小结详解

    本文从实际使用经验出发,介绍一款开源的MySQL数据库InnoDB数据恢复工具:innodb-tools,它通过从原始数据文件中提取表的行记录,实现从丢失的或者被毁坏的MySQL表中恢复数据.例如,当你不小心执行DROP TABLE.TRUNCATE TABLE或者DROP DATABASE之后,可以通过以下方式恢复数据.以下内容大部分参考自:Percona Data Recovery Tool for InnoDB,文档是英文的,而且写的比较晦涩,这里是个人的实战经验总结,供大家参考学习.在介

  • MySQL数据库存储引擎介绍及数据库的操作详解

    目录 MySQL存储引擎 InnoDB存储引擎 MyISAM储存引擎 Memory存储引擎 Archive存储引擎 数据库的相关操作 创建数据库 修改数据库 删除数据库 查看数据库列表 打开数据库 MySQL存储引擎 InnoDB存储引擎 InnoDB存储引擎是MySQL常见的的存储引擎, 它给MySQL的表提供了事务处理.回滚.崩溃修复和多版本并发控制等功能: 支持列值自动增长(列值不能为空且必须唯一): 支持外键. 缺点: 占用的空间相对较大 MyISAM储存引擎 MyISAM储存引擎支持3

  • MySQL数据库存储引擎和分支现状分析

    MySQL随着相应的各主创和内部开发人员的离去,缔造了各个不同的引擎和分支,让MySQL有希望继续发扬光大起来. 在MySQL经历了2008年Sun的收购和2009年Oracle收购Sun的过程中,基本处于停滞发展的情况,在可以预见的未来,MySQL是肯定会被Oracle搁置并且逐步雪藏消灭掉的.MySQL随着相应的各主创和内部开发人员的离去,缔造了各个不同的引擎和分支,让MySQL有希望继续发扬光大起来. 本文大致讲解一下MySQL目前除了主要的 MyISAM.InnoDB.Heap(Memo

  • MySQL的InnoDB引擎入门学习教程

    MySQL发展到今天,InnoDB引擎已经作为绝对的主力,除了像大数据量分析等比较特殊领域需求外,它适用于众多场景.然而,仍有不少开发者还在"执迷不悟"的使用MyISAM引擎,觉得对InnoDB无法把握好,还是MyISAM简单省事,还能支持快速COUNT(*).本文是由于最近几天帮忙处理discuz论坛有感而发,希望能对广大开发者有帮助. 1. 快速认识InnoDB InnoDB是MySQL下使用最广泛的引擎,它是基于MySQL的高可扩展性和高性能存储引擎,从5.5版本开始,它已经成为

  • MySQL禁用InnoDB引擎的方法

    一.确定版本 查看MySQL版本 复制代码 代码如下: mysql -V 或者可以登录MySQL使用select version();或status;命令查看 二.开始工作 关闭MySQL 复制代码 代码如下: service mysql stop 如果上面的命令无法关闭MySQL,则使用kill -9命令强制杀掉进程: 修改MySQL配置文件my.cnf(通常位于/etc/mysql/my.cnf)下加入如下字段 对于MySQL 5.5而言: 复制代码 代码如下: default-storag

  • MySQL数据库innodb启动失败无法重启的解决方法

    问题介绍 电脑在使用过程中死机,重启后发现mysql没有启动成功,查看错误日志发现是innodb出现问题导致mysql启动失败. 错误日志 $ mysql.server start Starting MySQL . ERROR! The server quit without updating PID file (/usr/local/var/mysql/fdipzonedeMacBook-Air.local.pid). 22:08:37 mysqld_safe Starting mysqld

  • 详解MySQL下InnoDB引擎中的Memcached插件

    前些年,HandlerSocket的横空出世让人们眼前一亮,当时我还写了一篇文章介绍了其用法梗概,时至今日,由于种种原因,HandlerSocket并没有真正流行起来,不过庆幸的是MySQL官方受其启发,研发了基于InnoDB的Memcached插件,总算是在MySQL中延续了NoSQL的香火,以前单独架设Memcached服务器不仅浪费了内存,而且还必须自己维护数据的不一致问题,有了Memcached插件,这些问题都不存在了,而且借助MySQL本身的复制功能,我们可以说是变相的实现了Memca

随机推荐