@

一、MySQL服务器逻辑架构

MySQL核心部分包括查询解析、分析、优化、缓存以及内置函数,所有跨存储引擎的功能,存储过程、触发器、视图等。

存储引擎负责MySQL中数据的存储和提取。服务器通过API和存储引擎进行通信。存储引擎API包含几十个底层函数,用于执行诸如“开始一个事务”或“根据主键查询数据”等操作,但存储引擎不会去解析SQL,不同存储引擎之间也不会相互通信,而只是简单地响应上层服务器的请求。

二、并发控制

1、读写锁

读锁是共享的,或者说是互不阻塞的,多个用户在同一时刻可以同时读取同一个资源,而互不打扰。

写锁则是排它锁,写锁会阻塞其它的写锁和读锁。

2、锁粒度

获取锁、检查锁是否被占用、释放锁等操作,都会增加系统的开销。

锁策略的意思就是在锁的开销和数据的安全性之间寻求平衡。

3、表锁

表锁是开销最小的锁,表锁 = 锁住整张表。

一个用户在对表进行写操作前,需要先获得写锁,这会阻塞其它用户对该表的读写操作。没有写锁时,其它用户会获取读锁,读锁之间互不阻塞。

尽管存储引擎可以管理自己的锁,MySQL还是会使用各种高效的表锁来实现不同的目的。比如,ALTER TABLE语句使用的就是表锁,而忽略存储引擎的锁机制。

4、行级锁

行级锁可以最大程度的支持并发处理,但也带来了最大的锁开销。

三、事务

事务内的语句,要么全执行,要么全不执行。事务具有ACID特性,ACID表示原子性(atomicity)、一致性(consistency)、隔离性(isolation)、持久性(durability)。

1、原子性(atomicity)

一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全执行提交成功,要么全不失败回滚。

2、一致性(consistency)

数据库总是从一个一致性的状态转换到另一个一致性的状态。

3、隔离性(isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。

4、持久性(durability)

事务一旦提交,则七所做的修改就会永久的保存在数据库中。

四、隔离级别

1、未提交读 read uncommited

在read uncommited级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这会导致很多问题,实际应用中很少使用。

2、提交读 read commited

大多数数据库系统的默认隔离级别都是 read commited,但MySQL不是, read commited满足前面提到的隔离性,一个事务开始时,只能看见已经提交的事务所做的修改。也称为不可重复读,因为两次执行同样的查询,可能会得到不一样的结果。

3、可重复读 repeatable read

repeatable read 解决了脏读的问题,该级别保证了在同一个事务中多次读取同样的记录的结果是一致的。但还是解决不了幻读的问题,幻读指的是当某个事务在读取某个范围内的记录时,另一个事务又在该氛围内插入了新的记录,档之前的事务再次读取该范围的记录时,会产生幻行。

可重复读是MySQL的默认事务隔离级别。

4、可串行化 serializable

serializable是最高级别的锁,它通过强事务串行执行,避免了之前说的幻读问题,serializable会在读取的每一行数据上都加锁,可能会导致大量的超时和锁争用问题,实际应用中很少使用这个隔离级别。

五、死锁

死锁是指两个或多个事务在同一个资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。当多个事务视图以不同的顺序锁定资源时,就可能会产生死锁。如果两个事务都尝试去执行一条相同的update语句,却发现该行已经被对方锁定,然后两个事务都等待对方释放锁,同时又持有对方需要的锁,则陷入死锁。

为了解决死锁问题,比如MySQL的InnoDB存储引擎,如果检测到死锁的循环依赖,InnoDB会将持有最少行级锁的事务进行回滚。

六、事务日志

存储引擎在修改表的数据时只需修改其内存拷贝,再把该修改行为记录在磁盘的事务日志中,而不是每次都将修改的数据本身持久到磁盘。

事务日志采用的是追加方式,事务日志在持久化之后,内存中被修改的数据会在后台慢慢的存入磁盘,但如果此时发生了异常,存储引擎在重启后,也会根据事务日志,将数据存到磁盘中。

七、多版本并发控制MVCC

MySQL的大多数事务型存储引擎实现的都不是简单的行级锁。基于提升并发性能的考虑,它们一般都同时实现了多版本并发控制MVCC,可以认为MVCC是行级锁的一个变种,但MVCC在很多情况下避免了加锁操作,开销比行级锁要低的多。

MVCC是通过保存某个时间点的快照实现的,不管需要执行多长时间,每个事物看到的数据都是一致的。根据事务开始的时间不同,每个事物对同一张表,同一时刻看到的数据可能是不一致的。

InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列实现的,一个保存了行的创建时间,一个保存行的删除时间。存储的并不是实际的时间值,而是系统版本号。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来和查询到的每行记录的版本号进行对比。

MVCC只在提交读 read commited、可重复读 repeatable read两个隔离级别中使用。

分别分析增删改查时,MVCC的使用。

1、select

InnoDB会根据以下两个条件检查每行记录:

  1. InnoDB只查找版本早于当前事务版本的数据行,这样保证事务读取的行,要么是在事务开始前就存在的,要么是事务自身插入或修改的;
  2. 行的删除版本要么未定义,要么大于当前事务版本号,这样保证事务读取的行,在事务开始前未被删除;

2、insert

InnoDB为新插入的每一行保存当前系统版本号作为行版本号。

3、update

InnoDB会插入一行新纪录,保存当前系统版本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除表示。

4、delete

InnoDB为删除的每一行保存当前系统版本号作为行删除标识。

保存这两个额外的系统版本号,使大多数读操作都可以不用加锁,MVCC的设计是的读数据很简单,性能很好,并且也能保证只会读到符合要求的行,不足之处是每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作。

MySQL进阶实战2,那些年学过的事务的更多相关文章

  1. MySQL进阶实战5,为什么查询速度会慢

    一.先了解一下MySQL查询的执行过程 MySQL在查询时,它是由很多子任务组成的,每个子任务都会消耗一定的时间,如果要想优化查询,实际上要优化其子任务,可以消除一些子任务.减少子任务的执行次数.让子 ...

  2. MySQL进阶实战1,数据类型与三范式

    一.选择优化的数据类型 MySQL支持的数据类型非常多,选择正确的数据类型对于获得高性能至关重要. 1.更小的 一般情况下,应该尽量使用较小的数据类型,更小的数据类型通常更快,因为占用更少的磁盘.内存 ...

  3. MySQL进阶实战4,MySQL索引详解,下篇

    一.索引 索引是存储引擎用于快速查找记录的一种数据结构.我觉得数据库中最重要的知识点,就是索引. 存储引擎以不同的方式使用B-Tree索引,性能也各有不同,各有优劣.例如MyISAM使用前缀压缩技术使 ...

  4. MySQL进阶实战3,mysql索引详解,上篇

    一.索引 索引是存储引擎用于快速查找记录的一种数据结构.我觉得数据库中最重要的知识点,就是索引. 存储引擎以不同的方式使用B-Tree索引,性能也各有不同,各有优劣.例如MyISAM使用前缀压缩技术使 ...

  5. MySQL进阶实战6,缓存表、视图、计数器表

    一.缓存表和汇总表 有时提升性能最好的方法是在同一张表中保存衍生的冗余数据,有时候还需要创建一张完全独立的汇总表或缓存表. 缓存表用来存储那些获取很简单,但速度较慢的数据: 汇总表用来保存使用grou ...

  6. MySQL进阶实战7,查询的执行过程

    @ 目录 一.拆分查询 二.分解关联查询 三.查询的执行过程 四.优化器的一些优化手段 1.重新定义关联表的顺序 2.将外连接转化为内连接 3.使用增加变换规则 4.优化count().max().m ...

  7. 【Python高级工程师之路】入门+进阶+实战+爬虫+数据分析整套教程

    点击了解更多Python课程>>> 全网最新最全python高级工程师全套视频教程学完月薪平均2万 什么是Python? Python是一门面向对象的编程语言,它相对于其他语言,更加 ...

  8. 最新Python3.6从入门到高级进阶实战视频教程

    点击了解更多Python课程>>> 最新Python3.6从入门到高级进阶实战视频教程 第1篇 Python入门导学 第2篇 Python环境装置 第3篇 了解什么是写代码与Pyth ...

  9. Linux Capabilities 入门教程:进阶实战篇

    原文链接:https://fuckcloudnative.io/posts/linux-capabilities-in-practice-2/ 该系列文章总共分为三篇: Linux Capabilit ...

随机推荐

  1. 基于.NET6的简单三层管理系统

    前言 笔者前段时间搬砖的时候,有了一个偷懒的想法:如果开发的时候,简单的CURD可以由代码生成器完成,相应的实体.服务都不需要再做额外的注册,这样开发人员可以省了很多事. 于是就开了这个项目,期望实现 ...

  2. 解决RHEL7.3系统找不到yum命令,无法使用YUM源的问题

    前言 RHEL的YUM源需要注册用户才能更新使用,由于CentOS和RHEL基本没有区别,并且CentOS已经被REHL收购.所以将RHEL的YUM源替换为CentOS即可. [root@NISEC- ...

  3. windows系统下使用bat脚本文件设置MySQL系统环境变量

    说明:在一个bat文件中设置tomcat环境变量后,不能直接使用,需要另起一个bat文件才能使用 号开头的行不要写在bat文件中 # 这个bat文件实现的功能:设置环境变量 @echo off set ...

  4. Winsw将jar包部署为windows服务

    1. 下载Winsw https://github.com/winsw/winsw/releases 下载winsw官网上的xml文件和.exe文件 2. 编辑配置文件 创建一个文件夹demo,将所需 ...

  5. 使用 PushGateway 进行数据上报采集

    转载自:https://cloud.tencent.com/developer/article/1531821 1.PushGateway 介绍 Prometheus 是一套开源的系统监控.报警.时间 ...

  6. Nginx代理和动静分离

    Nginx代理 微服务项目可能需要 Nginx来实现反向代理,用户请求 Nginx,随后 Nginx将请求转发至 Gateway网关,再由网关转至具体的微服务 一.动态代理 1.1 网关配置 针对使用 ...

  7. 关于for循环当中发生强制类型转换的问题

    Map map1 = new HashMap(); Map map2 = new HashMap(); Map map3 = new HashMap(); List<Map> list = ...

  8. AVX图像算法优化系列二: 使用AVX2指令集加速查表算法。

    查表算法,无疑也是一种非常常用.有效而且快捷的算法,我们在很多算法的加速过程中都能看到他的影子,在图像处理中,尤其常用,比如我们常见的各种基于直方图的增强,可以说,在photoshop中的调整菜单里8 ...

  9. JAVA员工名字 年龄 工资 工种

    如题: 下面是我个人的写法 输出部分使用了 格式化输出 有兴趣的朋友可以了解一下: 解决的思路大致为: 创建一个对象数组--> 数组下标为0的数组中张三这个变量对应 String name; 2 ...

  10. 驱动开发:内核枚举PspCidTable句柄表

    在上一篇文章<驱动开发:内核枚举DpcTimer定时器>中我们通过枚举特征码的方式找到了DPC定时器基址并输出了内核中存在的定时器列表,本章将学习如何通过特征码定位的方式寻找Windows ...