代码编织梦想

什么是MVCC:

MVCC(Multi Version Concurrency Control的简称),代表多版本并发控制。与MVCC相对的,是基于锁的并发控制,Lock-Based Concurrency Control)。

MVCC最大的优势:读不加锁,读写不冲突。在读多写少的OLTP应用中,读写不冲突是非常重要的,极大的增加了系统的并发性能学习MVCC前,我们先了解下Mysql架构和数据库事务隔离级别

MySQL 架构:

MySQL的架构不同于其他数据库,它的插件式的存储引擎架构可以在多种不同场景中应用并发挥良好作用。这种架构可以根据业务的需求和实际需要选择合适的存储引擎。

各层介绍:

1、连接层
最上层是客户端,包含本地sock通信和大多数基于客户端/服务端工具实现的类似于tcp/ip的通信。

2、服务层


3、引擎层

存储引擎负责MySQL中数据的存储和提取,服务器通过API与存储引擎进行通信。不同的存储引擎具有的功能不同,这样我们可以根据自己的实际需要进行选取。

show engines:查看所有的数据库引擎

show variables like ‘%engine%’ 查看默认的数据库引擎

 

MyISAM和InnoDB对比

4、存储层
数据存储层,主要是将数据存储在运行于裸设备的文件系统之上,并完成与存储引擎的交互。

四种数据库事务隔离级别:

为了解决并发事务存在的脏读、不可重复读、幻读等问题,数据库设计了四种隔离级别。分别是读未提交,读已提交,可重复读,串行化(Serializable)。

1、读未提交

读未提交隔离级别,只限制了两个数据不能同时修改,但是修改数据的时候,即使事务未提交,都是可以被别的事务读取到的,这级别的事务隔离有脏读、重复读、幻读的问题;

2、读已提交

读已提交隔离级别,当前事务只能读取到其他事务提交的数据,所以这种事务的隔离级别解决了脏读问题,但还是会存在重复读、幻读问题;

3、可重复读

可重复读隔离级别,限制了读取数据的时候,不可以进行修改,所以解决了重复读的问题,但是读取范围数据的时候,是可以插入数据,所以还会存在幻读问题;

4、串行化

事务最高的隔离级别,在该级别下,所有事务都是进行串行化顺序执行的。可以避免脏读、不可重复读与幻读所有并发问题。但是这种事务隔离级别下,事务执行很耗性能。

四种隔离级别具体特性

5、数据库是如何保证事务的隔离性的呢?

数据库是通过加锁,来实现事务的隔离性的。这就好像,如果你想一个人静静,不被别人打扰,你就可以在房门上加上一把锁。

加锁确实好使,可以保证隔离性。比如串行化隔离级别就是加锁实现的。但是频繁的加锁,导致读数据时,没办法修改,修改数据时,没办法读取,大大降低了数据库性能。

那么,如何解决加锁后的性能问题的?

答案就是,MVCC多版本并发控制!它实现读取数据不用加锁,可以让读取数据同时修改。修改数据时同时可读取。

MVCC实现:

MVCC是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number)。

每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行比较。

下面看一下在REPEATABLE READ隔离级别下,MVCC具体是如何操作的。

  • SELECTInnoDB会根据以下两个条件检查每行记录:
    1. InnoDB只查找版本早于当前事务版本的数据行(也就是,行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前已经存在的,要么是事务自身插入或者修改过的。
    2. 行的删除版本要么未定义,要么大于当前事务版本号。这可以确保事务读取到的行,在事务开始之前未被删除。
  • INSERTInnoDB为新插入的每一行保存当前系统版本号作为行版本号。
  • DELETEInnoDB为删除的每一行保存当前系统版本号作为行删除标识。
  • UPDATEInnoDB为插入一行新记录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。
    保存这两个额外系统版本号,使大多数读操作都可以不用加锁。这样设计使得读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行,不足之处是每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作

举例说明:

create table mvcctest( 
id int primary key auto_increment, 
name varchar(20));
create table mvcctest( 
id int primary key auto_increment, 
name varchar(20));

transaction 1:

start transaction;
insert into mvcctest values(NULL,'mi');
insert into mvcctest values(NULL,'kong');
commit;
start transaction;
insert into mvcctest values(NULL,'mi');
insert into mvcctest values(NULL,'kong');
commit;

假设系统初始事务ID为1;

transaction 2:

start transaction;
select * from mvcctest;  //(1)
select * from mvcctest;  //(2)
commit
start transaction;
select * from mvcctest;  //(1)
select * from mvcctest;  //(2)
commit

SELECT:

假设当执行事务2的过程中,准备执行语句(2)时,开始执行事务3:

transaction 3:

start transaction;
insert into mvcctest values(NULL,'qu');
commit;
start transaction;
insert into mvcctest values(NULL,'qu');
commit;

事务3执行完毕,开始执行事务2 语句2,由于事务2只能查询创建时间小于等于2的,所以事务3新增的记录在事务2中是查不出来的,这就通过乐观锁的方式避免了幻读的产生。

UPDATE:

假设当执行事务2的过程中,准备执行语句(2)时,开始执行事务4:

transaction session 4:

start transaction;
update mvcctest set name = 'fan' where id = 2;
commit;
start transaction;
update mvcctest set name = 'fan' where id = 2;
commit;

InnoDB执行UPDATE,实际上是新插入了一行记录,并保存其创建时间为当前事务的ID,同时保存当前事务ID到要UPDATE的行的删除时间。

事务4执行完毕,开始执行事务2 语句2,由于事务2只能查询创建时间小于等于2的,所以事务修改的记录在事务2中是查不出来的,这样就保证了事务在两次读取时读取到的数据的状态是一致的。

DELETE:

假设当执行事务2的过程中,准备执行语句(2)时,开始执行事务5:

transaction session 5:

start transaction;delete from mvcctest where id = 2;commit;

事务5执行完毕,开始执行事务2 语句2,由于事务2只能查询创建时间小于等于2、并且过期时间大于等于2,所以id=2的记录在事务2 语句2中,也是可以查出来的,这样就保证了事务在两次读取时读取到的数据的状态是一致的。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/m0_38048955/article/details/129678704

mysql锁机制详解_走出去拍拍照的博客-爱代码爱编程

一、概述         锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除了传统的计算资源的争用外,数据也是一种供许多用户共享的资源。为了保证数据并发访问的一致性和有效性,我们引入了锁。本文就是讨论MySQL锁机制的特点,常见的锁问题等。        针对不同的机制,从使用的方式,我们可以将锁分成乐观锁和悲观锁;如果按照粒度,我们可

事务详解_chongkan6148的博客-爱代码爱编程

1. MySQL中的本地事务 1.1 什么是事务 事务是逻辑上的一组操作,要么都执行,要么都不执行,一荣俱荣,一损俱损。数据库事务有严格的定义,必须满足4个特性。 原子性:事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;一致性:执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相

数据库详解(全)-爱代码爱编程

库表基础属性 mysql操作 mysql表操作 mysql表内容操作 mysql查询流程 存储引擎 数据记录存储格式 系统表汇总 建表规范 建表约束 字段类型 sql函数 存储过程 sql关键字

深入浅出-MySQL,到底什么是MySQL,它是怎么实现的?-爱代码爱编程

什么是MySQL? MySQL 是一种关系型数据库,在Java企业级开发中非常常用,因为 MySQL 是开源免费的,并且方便扩展。阿里巴巴数据库系统也大量用到了 MySQL,因此它的稳定性是有保障的。(悄悄告诉你,虽然咱们用的和阿里用的都是MySQL但是人家的是经过“改装的”哦)MySQL是开放源代码的,因此任何人都可以在 GPL(General Pub

mysql 表与表之间的条件比对_MySQL深入浅出锁分类及实现原理-爱代码爱编程

背景 数据库是一个多用户并发使用的共享资源。当多个并发读写数据时,在数据库中就会产生多个事务同时读写同一数据的情况。若对并发操作不加控制就可能会读取和存储不正确的数据,破坏数据库的一致性。这个时候就要引入「锁」的概念,来应对上面所说的并发情况。 简介 ❝ 锁是在执行多线程或者协程时用于强行限制资源访问的同步机制,即用

拨开云雾见天日:剖析单机事务原理-爱代码爱编程

点击上方“方志朋”,选择“置顶或者星标” 你的关注意义重大! 江湖传说:不了解数据库事务的程序员不是一个好的DBA。阅遍网上无数关于数据库事务的文章,都感觉云里雾里,不知所云。于是乎拍案而起,麻蛋,还是自己写吧。最后便有了这篇文章,它试图用通俗的文字来说明单机事务的ACID特性及其大致的实现原理。 一、什么是事务? 数据库事务(简称

2021年Java开发实战!深入浅出dockerpdf-爱代码爱编程

01 阿里中间件(四面,Java岗) 1.1 Java中间件一面 技术一面考察范围 重点问了Java线程锁:synchronized 和ReentrantLock相关的底层实现 线程池的底层实现以及常见的参数 数据结构基本都问了一遍:链表、队列等 Java内存模型:常问的JVM分代模型,以及JDK1.8后的区别,最后还问了JVM相关的调优参

mysql葵花宝典_artistpeng的博客-爱代码爱编程

一、MySQL 执行流程 先从一条简单的语句开启话题 // 在 product 表中,查询 id = 1 的记录 select * from product where id = 1; 执行一条 select 查询语句,在 MySQL 中期间发生了什么? 带着这个问题,我们来了解下MySQL 内部的架构 可以看到, MySQL 的架构共分

备忘录模式-爱代码爱编程

备忘录模式(Memento Pattern),也叫快照(Snapshot)模式,在不破坏封装性的前提下,捕获一个对象的内部状态,并在该对象之外保存这个状态;这样以后就可将该对象恢复到原先保存的状态。主要是用来防丢失、撤销、恢

网络编程-爱代码爱编程

网络编程 网络编程一、什么是网络二、计算机网络三、网络编程四、网络模型(OSI模型)五、TCP/IP模型六、TCP\UDP协议七、IP八、Port端口九、InetAddress类十、网络编程10.1 Socket编程