第1章 Mysql架构与历史


MYSQL最重要、最与众不同的特性是它的存储引擎架构,这种架构的设计将查询处理( Query Processing)及其他系统任务( Server Task)和数据的存储/提取相分离。这种处理和存储分离的设计可以在使用时根据性能、特性、以及其他需求来选择数据存储的方式。

MySQL逻辑架构

  • 第一层: 大多数基于网络的C/S的工具或服务都是类似的结构,比如连接处理 授权认证 安全
  • 第二层: 大多数MySQL 的核心服务功能都在这一层,包括查询解析、分析、优化、缓存以及所有的内置函数(日期、时间、数学和加密),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图
  • 第三层: 存储引擎负责Mysql中数据的存储和提取。和GUN/Linux下的各种文件系统一样,每个存储引擎都有它的优势和劣势。存储引擎不会解析SQL(InnoDB除外,它会解析外键定义,Mysql服务器本身没有实现该功能)不同的存储引擎也不会相互通信,只是响应上层服务器的请求,服务器通过API与存储引擎进行通信,且这些接口屏蔽了不同存储引擎之间的差异

修正认知错误:读了高性能Mysql才认识到,对于任意一个成熟的版本,它都是由服务端层+核心功能+存储引擎三部分构成,且对于同一个版本而言,选择的存储引擎不同,导致Mysql的性能和特点也大大不同

注:

  • Mysql 主要分为Server层(Server服务层 + 核心功能层)和引擎层,Server层主要包括连接器、查询缓存、分析器、优化器、执行器,同时还有一个日志模块(binlog),这个日志模块所有执行引擎都可以共用

  • 引擎层是插件式的,目前主要包括,MyISAM,InnoDB(默认),Memory等

  • 查询语句的执行流程如下:

查询缓存(命中缓存) —》权限校验

查询缓存(未命中缓存)—》分析器—》优化器—》权限校验—》执行器—》引擎

  • 更新语句执行流程如下:分析器----》权限校验----》执行器—》引擎—redo log(prepare 状态—》binlog—》redo log(commit状态)

连接管理及安全性

每个客户端连接都会在服务器进程中拥有一个线程,这个链接的查询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或CPU中运行。服务器会缓存线程,因此不需要为每一个新建的连接创建或者销毁线程。

Mysql服务在运行时即会创建好一个线程池,然后对接客户端请求,因此不需要为每一个新建的连接创建或者销毁线程

线程池的上限也决定了一个Mysql库难以承载高并发的需求

优化与执行

MYSQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写査询、决定表的读取顺序,以及选择合适的

素引等、同时用户可以通过特殊的关键字提示(hint)优化器,影响它的决策过程

这里想到了某天开发组长和一个组员争论的问题:

聚合索引a、b、c
在查询的时候不按照abc的顺序是否可以应用上索引,(explain select * from test where b = 1 and c = 1 and a = 1)

答案是肯定的,依然会通过索引查询,即是因为优化器的优化

并发控制

Mysql在解决并发场景下多个查询在同一时刻修改数据问题时,主要从服务层及存储引擎层进行控制

读写锁

和Java层面的读写锁类似,对于Mysql中共享锁及排他锁,即读写锁也是保证了读读之间共享,读写,写写间相互排斥

在实际的数据库系统中,每时每刻都在发生锁定,当某个用户在修改某一部分数据时MYSQL会通过锁定防止其他用户读取同一数据,

大多数时候, MYSQL锁的内部管理都是透明的

锁粒度

一种提高共享资源并发性的方式就是让锁定对象更有选择性。尽量只锁定需要修改的部分数据,而不是所有的资源。更理想的方式

是,只对会修改的数据片进行精确的锁定。任何时候,在给定的资源上,锁定的数据量越少,则系统的并发程度越高,只要相互之

间不发生冲突即可。但于此同时,锁本身也是一种开销,如果为了减少锁定的数据量导致锁本身占用资源过多,也是得不偿失。

因此大多数商业数据库一般都是在表上施加行级锁(row - level lock),并以各种复杂的方式来实现,以便在锁比较多的情况下尽

可能提供更好的性能

而Mysql则提供了多种方案选择,每种存储引擎都可以实现自己的锁策略和锁粒度,主要有两种:

表锁:

故名意思即锁定整个表,需要注意的是写锁比读锁具有更高的优先级,因此一个写锁请求可以优先于读锁请求执行

另外,尽管各个存储引擎可以实现自己的锁机制,但是Mysql服务端会为诸如ALTER,TABLE之类的语句使用表锁,而忽略存储引擎

自己的策略

行级锁:

行级锁策略在Mysql服务端完全没有实现,都是借由存储引擎实现,如:InnoDB

事务

事务具有四个必要特性:

原子性(A):不可分割的最小单位

一致性(C):要么都成功要么都失败

隔离性(I):事务之间不可见

持久性(D):事务提交,永久生效

隔离级别

  • READ UNCIMMITTED(未提交读):造成脏读,实际很少使用
  • READ COMMITTED(提交读 / 不可重复读): 两次执行同样的查询,可能会得到不一样的结果
  • REPEATABLE READ(可重复读):依然会有幻读(Phantom Read) 的问题,进一步通过多版本并发控制(Multi version Concurrency Control,MVCC)解决,是MySQL的默认隔离级别
  • SERIALIZABLE(串行化):在读取的每一行上都加上锁,可能导致大量的超时和锁争用,实际很少使用

死锁

死锁的必要条件:

  • 互斥:某种资源一次只允许一个进程访问
  • 占有且等待 : 一个进程本身占有资源(一种或多种),同时还有资源未得到满足,正在等待其他进程释放该资源
  • 不可抢占:无法抢占其他已被占用的资源
  • 循环等待:存在一个进程链,使得每个进程都占有下一个进程所需的至少一种资源

为了解决这种问题,数据库系统实现了各种死锁检测和死锁超时机制。越复杂的系统,比如 INNODB存储引擎,越能检测到死锁的

循环依赖,并立即返回一个错误,且在同一个场景中由于存储引擎不同,A引擎可能产生死锁,B则不会

事务日志

使用事务日志,存储引擎在修改数据时只需要把修改行为记录到硬盘的事务日志中,而不用每次都将修改的数据本身持久到硬盘。

事务日志采用的是追加的方式,写日志操作是磁盘上的顺序I/O,所以要快很多,事务日志持久以后,内存中被修改的数据可以在

后台慢慢刷回到磁盘,称之为预写式日志(Write-Ahead Logging),修改操作需要写两次磁盘

Mysql中的事务

Mysql提供了两种事务性的存储引擎:InnoDB 和 NDB Cluster

自动提交(AUTOCOMMIT)

Mysql默认采用自动提交(AUTOCOMMIT)的模式,如果不明确开始一个事务,则每个查询都被当做一个事务执行提交操作

在事务中混合使用存储引擎

Mysql服务器不管理事务,事务是由下层存储引擎实现的。混合使用事务型和非事务性的表不会有问题(例如 InnoDB 和 MyISAM),但是回滚时,非事务的表无法撤回

隐式和显示锁定

InnoDB 采用的是两阶段锁定协议(two-phase locking protocol),随时可执行锁定,在执行commit 后者rollback时会释放,这是隐式锁定

显示锁定(强烈不建议使用)

SELECT … LOCK IN SHARE MODE

SELECT … FOR UPDATE

多版本并发控制

多版本并发控制,即MVCC,该模块是基于提升并发性能的考虑,它是行级锁的一个变种,但是它在很多的情况避免了加锁的操

作,因此开销更低,虽然实现机制有所不同,但大都实现了非阻塞的读操作,写操作也只锁定必要的行

INNODB的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的。这两个列,一个保存了行的创建时间,一个保存行的过期时间

(或删除时间)。当然存储的并不是实际的时间值,而是系统版本号( system version number)。每开始一个新的事务,系统版本号都

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

我个人感觉MVCC的策略和Java8中的乐观读写锁- StampedLock 非常相似,通过乐观锁的思路,减少悲观锁的使用和阻塞的情况发生,StampedLock 是通过对比邮戳整数Stamp,而Mysql通过对比系统版本号来决定需不需要完全加锁

Mysql的存储引擎

Mysql的存储引擎多种多样,远远不是很多面试答案中题到的:MyISAM及 InnoDB两种,通过高性能Mysql书中对于各种存储引擎的

介绍,在选择存储引擎时候大概率可以毋庸置疑的选择InnoDB

不过新的问题来了,什么是存储引擎:根据较新的Mysql版本,存储引擎早已支持插件化了,即一个Mysql存储引擎是实现了Mysql存储引擎基本接口的程序,可以以插件的形式与Mysql数据库一同工作

也就是说,如果你能力足够强,你也可以完全自定义一个Mysql存储引擎

InnoDB概览

InnoDB采用mvcc来支持高并发,实现了四个标准的隔离级别,默认级别是REPEATABLE READ(可重复读),通过间隙锁(next-key

locking)策略防止幻读的出现。间隙锁使得InnoDB不仅仅锁定查询设计的行,还会对索引中的间隙进行锁定,防止幻影行的插入.

InnoDB是通过聚簇索引建立的,InnoDB的索引结构和其他存储引擎有很大的不同,聚簇索引对主键查询有很高的性能,但二级索

引必须包含主键列,如果主键列很大的话,其他的所有索引都会很大。因此弱表上的索引较多的话,主键应当尽可能的小。InnoDB

的存储格式是平台独立的,可以将数据和索引文件从Intel平台复制到PowerPC或者Sun SPARC.

InnoDB 内部做了很多优化,包括从磁盘读取数据时采用的可预测性预读,能够自动在内存中创建hash索引以加速读操作的自适应

哈希索引,以及能够加入检查入操邹的插入缓冲区(insert buffer)

Mysql的其他存储引擎不支持热备份,要获取一致性视图需要停止对所有表的写入。

MyISAM引擎

Mysql 5.1及以前的版本,MyISAM是默认的储存引擎。提供了大量的特性,包括全文索引 压缩 空间函数(GIS),但MyISAM不支持事务

和行级锁,而且有一个大的缺陷,崩溃后无法修复。

优势:存储数据支持压缩,占用较小

提醒:绝对不要混用存储引擎!!!

【高性能Mysql 】读书笔记(一)相关推荐

  1. 高性能MySQL读书笔记 (五)

    1. 优化服务器设置 MySQL有大量的可以修改的参数,但不应该随便修改.应该将更多时间花在schema的优化,索引,查询设计上 配置文件路径: 通常在/etc/my.cnf 不建议动态修改变量,因为 ...

  2. 高性能MySQL读书笔记---查询优化

    查询优化 查询缓慢的原因 是否向数据库请求了不必要的数据 1.查询时是否返回了全部或者大部分数据然后再进行处理的. 2.进行单查或者多表联查时是否返回了全部列数据.例如: SELECT * FORM ...

  3. 高性能MYSQL读书笔记1

    一. 1 每个 客户端连接都会在服务器进程中拥有一个线程,这个连接的查询只会在这个单独的线程中执行,该线程只能轮流在某个CPU核心或者cpu中运行.服务器会负责缓存线程,因此不需要为每一个新建的连接创 ...

  4. 高性能MySQL读书笔记

    数据类型 整数类型 类型 位数 TINYINT 8 SMALLINT 16 MEDIUMINT 24 INT 32 BIGINT 64 int(1) 和int(28)存储的位数相同,mysql不会限制 ...

  5. mysql数据库介绍笔记_MySQL数据库之MySQL读书笔记

    本文主要向大家介绍了MySQL数据库之MySQL读书笔记,通过具体的内容向大家展现,希望对大家学习MySQL数据库有所帮助. mysql> CREATE TABLE tb6( -> id  ...

  6. 高性能MySQL读书计划

    知识星球 码农翻身(作者:刘欣)的读书活动 读书群规则: 入群需要交100元押金, 每周需要交作业输出一篇不少于200字的读书笔记, 读书分三阶段进行, 如果每个阶段没交作业的次数>=2 , 押 ...

  7. 高性能mysql学习笔记--复制

    高性能mysql 十:复制 1,复制的概述 复制解决的基本问题是让一台服务器的数据与其他服务器要保持同步. 两种方式:基于行的复制和基于语句的复制,都是通过在主库上记录二进制日志,在备库上重放日志来实 ...

  8. 高性能mysql学习笔记--索引

    高性能mysql 五:索引 1,B-Tree索引 全值匹配:匹配所有列. 匹配最左前缀:只使用索引的第一列. 匹配列前缀:只使用索引的第一列. 匹配范围值:只使用索引的第一列. 精确匹配某一列并范围匹 ...

  9. 高性能mysql学习笔记--高级特性

    高性能mysql 七:高级特性 1,分区表 分区表是一个独立的逻辑表,但是底层由多个无力字表组成,实现分区的代码实际上是对一组地层表的句柄对象的封装,对分区表的请求,都会通过句柄对象转化成对储存引擎的 ...

  10. 高性能MySQL读书摘要(五)创建高性能的索引

    索引优化应该是最有效的优化手段了."最优"的索引有时比一个"好的"索引性能要好两个数量级.创建一个真正的"最优"的索引经常需要重写查询,所以 ...

最新文章

  1. [源码和文档分享]基于Netty和WebSocket的Web聊天室
  2. 无异常日志,就不能排查问题了???
  3. oracle logminer全解析
  4. linux集群-keepalived介绍-用keepalived配置高可用集群
  5. Perl Nmap报告处理摸索(学习)
  6. 解决服务间调用的三种传统方式
  7. boost::ratio_negate相关的测试程序
  8. 2021HDU多校7 - 7054 Yiwen with Formula(分治MTT优化dp)
  9. 英语人机考试计算机算分吗,英语人机对话考试技巧
  10. CentOS6.5 linux 逻辑卷管理 调整分区大小:/dev/mapper/VolGroup-lv_root 50G 47G 16M 100%
  11. 在MyEclipse中安装SVN插件subclipse
  12. css如何设置动画,css3如何设置动画?css设置简单动画的方法
  13. 帆软报表开发之基础操作
  14. 水经注下载的地图版权_怎么下载天地图地方高清影像
  15. 【企业了解】巨量引擎(飞鱼CRM)
  16. 坚持十年博客写作,不忘初心,方得始终
  17. Redhat8.0 安装web consol、可视化管理工具
  18. unipush+java+个推实现app消息推送
  19. 第二章:第二三节数据重构
  20. HashSet-哈希值

热门文章

  1. 运维工程师绩效考核表_IT运维绩效考核表
  2. python房屋租赁系统的设计与实现_毕业设计---在线房屋租赁系统的设计与实现.doc...
  3. stc15w204s步进电机c语言,stc15w204s串口求救
  4. 小程序打通了用户到店的最后一步!
  5. ramda 函数 Function
  6. linux 儒略日时间计算,C/C++ 儒略日计算以及恒星时计算
  7. 各国货币名称中英对照
  8. 三角函数的正交性及其公式推导
  9. Python数据分析师工资怎么样?
  10. url 转码 java_java中URL转码