java基础巩固-宇宙第一AiYWM:为了维持生计,MySQL基础Part6(关系型数据库与非关系型数据库、MySQL&PostgreSQL特别之处、MySQL 执行查询/更新的过程、执行引擎)~整起

PART1:NOSQL和关系型数据库比较

  • NoSQL的故事:NoSQL(非关系型数据库,不仅仅是数据库),可以根据对象自身的属性来存储对象。NoSQL(NoSQL = Not Only SQL),意即“不仅仅是SQL”,是一项全新的数据库理念,泛指非关系型的数据库。
    • 咱们平时可能做项目的时候,会涉及到技术选型,放到咱们这个系列中,我该用哪个数据库呢?
      • 关于这种新技术,架构师最重要的就是技术选型、技术对比【https://db-engines.com/en/system/Redis,到这个网站比较比较,看这个数据库的特性,比其他的DB好多少,是不是咱们需要的】,
    • 为什么要用NoSQL
      • (现如今,数据量大,而且数据变化很快存的东西种类很多图片呀视频呀所以找专业的来处理不同种类的):
      • 单机MySQL时,数据量太大一个机器放不下;
        在这里插入图片描述
        在这里插入图片描述
      • 数据索引(B+Tree),一个服务器也放不下;
      • 访问量(读写混合),一个服务器承受不了
    • 主流的四种NOSQL产品:
      • 文档型数据库:
        在这里插入图片描述
        • MongoDB:有时候数据的最佳表现形式是文档,并且虽然文档是独立的实体,但是多个文档之间也可能会产生关联。文档数据库能够去优化并处理文档
          • Spring Data MongoDB提供了三种方式在Spring应用中使用MongoDB:
            • 通过注解实现对象-文档映射;
            • 使用MongoTemplate实现基于模板的数据库访问;
            • 自动化的运行时Repository生成功能。
      • 列存储数据库:
        在这里插入图片描述
      • 图形(Graph)数据库:放的是咱们的比如社交网络的关系的
        在这里插入图片描述
      • 文档型数据库会将数据存储到粗粒度的文档中,而**图数据库会将数据存储到多个细粒度的节点中,这些节点之间通过关系建立关联**。图数据库中的一个节点通常会对应数据库中的一个概念(concept) ,它会具备描述节点状态的属性。连接两个节点的关联关系可能也会带有属性。按照其最简单的形式,图数据库比文档数据库更加通用,有可能会成为关系型数据库的无模式(schemaless)替代方案。因为数据的结构是图,所以可以遍历关联关系以查找数据中你所关心的内容,这在其他数据库中是很难甚至无法实现的。
      • 键值(Key-Value)存储数据库: Tokyo Cabinet/Tyrant、Redis、Voldemort、Berkeley DB
        • Redis与比如Memecached相比有哪些优势【缓存的技术有很多,比如memcached、Redis
          在这里插入图片描述
          • memcached的value没有类型的概念,而redis的value有5+3类型,这是他俩的一个重要区别。那么memcached当时用的时候咋存多个键值对的?------>JSON,我memcached的value可以是JSON,然后JSON可以放不同形式的东西,既然这样可以存不同类型的东西,那还要redis干什么?
          • 因为当客户端获取value时memcached会返回value所有的数据,redis对每种类型都有自己对应的方法,对症下药,相对应取起来就很快----------->计算【解析JSON字符串】向数据移动
        • 为什么要用 Redis 而不用 map/guava 做缓存?
          在这里插入图片描述
          • 缓存分为本地缓存和分布式缓存。【以java为例,使用自带的map或者guava实现的是本地缓存,最主要的特点是轻量以及快速,生命周期随着jvm的销毁而结束,并且在多实例的情况下,每个实例都需要各自保存一份缓存,缓存不具有一致性。】
            • 使用Redis或memcached之类的称为分布式缓存,在多实例的情况下,各实例共用一份缓存数据,缓存具有一致性。缺点是需要保持Redis或memcached服务的高可用,整个程序架构上较为复杂
        • 那为什么要用缓存?
          • 硬盘慢,为什么慢,除了磁头寻址慢,还有带宽(单位时间内流过的字节数)也是一个拖后腿条件
  • 数据库系统与文件系统很大的一一个不同之处在于对事务的支持,我如果只是简单的报表查询我就不需要支持事务呀,用不上我支持他干嘛?在这里插入图片描述
    一般咱们经常说去关系型数据库,就是MySQL;说起非关系型数据库,就是Redis,为啥呢?
  • MySQL不完美但是很灵活并且能够适应高要求的环境,此外
    在这里插入图片描述
  • MySQL最重要、最与众不同的就是MySQL的存储引擎架构,他的架构将查询处理以及其他系统任务和数据的存储/提取相分离,分离之后咱们就可以在使用时根据性能、特性以及其他需求来选择数据存储的方式
    • 其实能用 MySQL 直接存储文件(比如图片),但是可以是可以,直接存储文件对应的二进制数据即可。不过,还是建议不要在数据库中存储文件,会严重影响数据库性能,消耗过多存储空间
    • MySQL 如何存储 IP 地址?
      • 可以将 IP 地址转换成整形数据存储,性能更好,占用空间也更小。MySQL 提供了两个方法来处理 ip 地址:插入数据前,先用 INET_ATON() 把 ip 地址转为整型,显示数据时,使用 INET_NTOA() 把整型的 ip 地址转为地址显示即可
        • INET_ATON() : 把 ip 转为无符号整型 (4-8 位)
        • INET_NTOA() :把整型的 ip 转为地址
  • 关系型和非关系型数据库的区别:
    • 关系型数据库的优点:
      • 采用了关系模型来组织数据,容易理解
      • 由于有事务的四个特性,可以保证数据的一致性等
      • 支持复杂查询(带 where 子句的查询)
    • 非关系型数据库(NOSQL)的优点:
      • 无需经过 SQL 层的解析,读写效率高
      • 可以支持多种类型数据的存储,如图片,文档以及基于键值对的,正如基于键值对的非关系型数据库,读写性能很高,易于扩展
      • 扩展(可分为内存性数据库以及文档型数据库,比如 Redis,MongoDB,HBase 等,适合场景:数据量大高可用的日志系统/地理位置存储系统)

另外,我们项目中用到了postgresql(pg)数据库,简单说一下:

  • PostgreSQL:MySQL自称是最流行的开源数据库,而PostgreSQL则标榜自己是最先进的开源数据库
    • 是一个功能强大的开源对象关系型数据库系统。开源是大众选择 PostgreSQL 的第一大理由,其次是可靠性和扩展
      • 一些 PostgreSQL 扩展:
        在这里插入图片描述
      • SQL、Python、Java、shell 脚本和 JavaScript / TypeScript 被列为访问 PostgreSQL 最常用的语言。在使用工具连接 PostgreSQL 进行查询和管理任务的受访者中,psql (69.4%)、pgAdmin (35.3%) 和 DBeaver (26.2%) 是前三位的选择。Grafana、pgAdmin 和 DBeaver 是最可能使用的可视化工具
    • 特点:
      • PostgreSQL支持大部分的SQL标准并且提供了很多其他现代特性,如复杂查询、外键、触发器、视图、事务完整性、多版本并发控制等。
      • PostgreSQL也可以用许多方法扩展,例如通过增加新的数据类型、函数、操作符、聚集函数、索引方法、过程语言等。另外,因为许可证的灵活,任何人都可以以任何目的免费使用、修改和分发PostgreSQL
      • 除了免费和开源之外,Postgre SQL还具有高度的可扩展性可以定义自己的数据类型构建自定义SQL函数,甚至可以编写来自不同编程语言的代码,而不需要重新编译数据库。
        在这里插入图片描述
        在这里插入图片描述

没有对比就没有伤害,来比比:MySQL和PostgreSQL

  • PostgreSQL的稳定性极强,Innodb等引擎在崩溃、断电之类的灾难场景下抗打击能力有了长足的进步,然而很多Mysql用户都遇到过Server级的数据库丢失的场景—Mysql系统库是MyISAM的,相较而言,PG数据库在这方面要好一些。
  • PostgreSQL支持存储一些特殊的数据类型,比如:array、json、jsonb
  • 任何系统都有他的性能极限,在高并发读写,负载逼近极限下,PG的性能指标仍然可以维持双曲线甚至对数曲线,到顶峰之后不再下降,而MySQL明细出现一个波峰后下滑
  • PG多年在GIS领域处于优势地位,因为它有丰富的几何类型,实际上不止几何类型,PG中有大量的字典、数组、bitmap等数据类型,相比之下MaySQL就差很多,insagram就是因为PG的空间数据库扩展POSTGIS远远强于MySQL的my spatial而采用PGSQL的。
  • PostgreSQL也支持外部数据源,可以把MySQL、Oracle、CSV、Hadoop等当成自己数据库中的表来进行查询
  • PostgreSQL对索引的支持更强,PostgreSQL支持 B-树、哈希、R-树和 Gist 索引。而MySQL取决于存储引擎。MyISAM:BTREE,InnoDB:BTREE。
  • PostgreSQL的事务隔离更好,MySQL 的事务隔离级别repeatable read并不能阻止常见的并发更新,得加锁才可以,但悲观锁会影响性能,手动实现乐观锁又复杂。而 PostgreSQL 的列里有隐藏的乐观锁 version 字段,默认的 repeatable read 级别就能保证并发更新的正确性,并且又有乐观锁的性能
    时间精度更高,可以精确到秒以下
  • PG有极其强悍的SQL编程能力,有丰富的统计函数和统计语法支持,比如分析函数(Oracle的叫法,PG里面叫Window函数),还可以用多种语言来写存储过程,对于R的支持也很好。这一点上MySQL就差的很远,很多分析功能那个都没有,腾讯内部数据存储主要是Mysql,但是主要的数据分析就是Hadoop+PGsql
  • 一般关系型数据库的字符串有限定长度8k左右,无限长Text类型的功能受限,只能作为外部大数据访问。而PG的TEXT类型可以直接访问,SQL语法内置正则表达式,可以索引,还可以全文检索,或使用xml xpath。用PG的话,文档数据库就可以省略了
    • 存储方式支持更大的数据量,PostgreSQL主表采用堆表存放,MySQL采用索引组织表,能够支持比MySQL更大的数据量
  • 对于web应用来说,复制的特性很重要,Mysql到现在也是异步复制,pgsql可以做到同步,异步,半同步复制。还有mysql的同步是基于binlog复制,类似oracle golden gate, 是基于stream的复制,做到同步很困难,这种方式更加适合异地复制,pgsql的复制基于wal,可以做到同步复制。同时pgsql还提供stream复制

PART2-1:MySQL 执行查询的过程(一条 MySQL 语句执行的步骤)【MySQL 执行一条 select 查询语句,在 MySQL 中期间发生了什么?】:Server 层按顺序执行 SQL 的步骤如下:连接器【建立连接,管理连接、校验用户身份】---->查询缓存【查询语句如果命中查询缓存则直接返回,否则继续往下执行。MySQL 8.0 已删除该模块;】---->解析SQL【通过解析器对 SQL 查询语句进行词法分析语法分析,然后构建语法树方便后续模块读取表名、字段、语句类型;】---->执行SQL【执行SQL共有三个阶段:预处理阶段:检查表或字段是否存在;将 select * 中的 * 符号扩展为表上的所有列。+ 优化阶段:基于查询成本的考虑, 选择查询成本最小的执行计划; + 执行阶段:根据执行计划执行 SQL 查询语句,从存储引擎读取记录,返回给客户端;】举两个例子:
例一:
在这里插入图片描述
例二:

// 在 product 表中,查询 id = 1 的记录
select * from product where id = 1;

在这里插入图片描述

  • 1.客户端先向连接器发出连接请求,通过连接器跟客户端建立连接:其实也就是咱们经常在服务器中执行的:mysql -uroot -p,然后输入密码…,从而进行Mysql服务的连接。
    • 连接器用来验证用户身份,给予权限
      在这里插入图片描述
      • 如果用户密码都没有问题,连接器就会获取该用户的权限,然后保存起来,后续该用户在此连接里的任何操作,都会基于连接开始时读到的权限进行权限逻辑的判断。
      • 所以,如果一个用户已经建立了连接,即使管理员中途修改了该用户的权限,也不会影响已经存在连接的权限。修改完成后,只有再新建的连接才会使用新的权限设置。
      • 可以执行show processlist命令来查看当前 MySQL 服务被多少个客户端连接了
        • MySQL 服务支持的最大连接数由 max_connections 参数控制,比如我的 MySQL 服务默认是 151 个,超过这个值,系统就会拒绝接下来的连接请求,并报错提示“Too many connections”。
          在这里插入图片描述
        • 怎么解决长连接占用内存的问题?有两种解决方式。大部分其他技术解决长连接的缺陷也是这两种思路:
          • 第一种,定期断开长连接。既然断开连接后就会释放连接占用的内存资源,那么我们可以定期断开长连接。
          • 第二种,客户端主动重置连接。MySQL 5.7 版本实现了 mysql_reset_connection() 函数的接口,注意这是接口函数不是命令,那么当客户端执行了一个很大的操作后,在代码里调用 mysql_reset_connection 函数来重置连接,达到释放内存的效果。这个过程不需要重连和重新做权限验证,但是会将连接恢复到刚刚创建完时的状态
      • MySQL 定义了空闲连接的最大空闲时长**,由 wait_timeout 参数控制的,默认值是 8 小时(28880秒),如果空闲连接超过了这个时间,连接器就会自动将它断开**。
    • 连接的过程需要先经过 TCP 三次握手,因为 MySQL 是基于 TCP 协议进行传输的,如果 MySQL 服务并没有启动,则会报错
    • 如果 MySQL 服务正常运行,完成 TCP 连接的建立后,连接器就要开始验证你的用户名和密码,如果用户名或密码不对,就收到一个"Access denied for user"的错误,然后客户端程序结束执行。
  • 2.通过查询缓存查询之前是否有查询过该 sql(MySQL 8.0 版本后移除,因为这个功能不太实用
    在这里插入图片描述
    • 有,也就是存在该sql查询相关的缓存,则直接返回结果
      • my.cnf 加入以下配置,重启 MySQL 开启查询缓存
        在这里插入图片描述
    • 没有则执行第三步
      • 任何两个查询在任何字符上的不同都会导致缓存不命中。
      • 除此之外,查询缓存不命中的情况还有如果查询中包含任何用户自定义函数、存储函数、用户变量、临时表、MySQL 库中的系统表,其查询结果也不会被缓存。
      • 缓存建立之后,MySQL 的查询缓存系统会跟踪查询中涉及的每张表,如果这些表(数据或结构)发生变化,那么和这张表相关的所有缓存数据都将失效
  • 3.通过分析器对SQL进行词法分析和语法分析操作。在正式执行 SQL 查询语句之前, MySQL 会先对 SQL 语句做解析,这个工作交由由解析器来完成。说白了第三步中分析器就是要先看你的 SQL 语句要干嘛,再检查你的 SQL 语句语法是否正确
    • 分析该 sql 的语义是否正确,包括格式,表等等
    • 解析器只负责构建语法树和检查语法,但是不会去查表或者字段存不存在。
    • 解析器会做如下两件事情:
      • 第一件事情,词法分析。MySQL 会根据你输入的字符串识别出关键字出来,构建出 SQL 语法树,这样方便后面模块获取 SQL 类型、表名、字段名、 where 条件等等。
      • 第二件事情,语法分析。根据词法分析的结果,语法解析器会根据语法规则判断你输入的这个 SQL 语句是否满足 MySQL 语法
        • 如果我们输入的 SQL 语句语法不对,就会在解析器这个阶段报错。
  • 4.通过优化器优化该语句,主要对执行的SQL优化选择最优的执行方案方法。说白了就是挑一个最高效的方法执行SQL语句【很多时候即使用了索引也有可能会走全表扫描,这是因为 MySQL 优化器的原因】
    • 经过解析器后,接着就要进入执行 SQL 查询语句的流程了,每条SELECT 查询语句流程主要可以分为下面这三个阶段
      • prepare 阶段,也就是预处理阶段;主要是预处理器发挥作用
        • 检查 SQL 查询语句中的表或者字段是否存在
        • 将 select * 中的 * 符号,扩展为表上的所有列;
      • optimize 阶段,也就是优化阶段;经过预处理阶段后,还需要为 SQL 查询语句先制定一个执行计划,这个工作交由优化器【优化器主要负责将 SQL 查询语句的执行方案确定下来,比如在表里面有多个索引的时候,优化器会基于查询成本的考虑,来决定选择使用哪个索引。】来完成的。
        • 要想知道优化器选择了哪个索引,我们可以在查询语句最前面加个 explain 命令,这样就会输出这条 SQL 语句的执行计划,然后执行计划中的 key 就表示执行过程中使用了哪个索引
          在这里插入图片描述
        • 如果查询语句的执行计划里的 key 为 null 说明没有使用索引,那就会全表扫描(type = ALL),这种查询扫描的方式是效率最低档次的
          在这里插入图片描述
        • 举个例子:这张 product 表只有一个索引就是主键,现在我在表中将 name 设置为普通索引(二级索引)。
          在这里插入图片描述
          • 这条查询语句是覆盖索引,直接在二级索引就能查找到结果(因为二级索引的 B+ 树的叶子节点的数据存储的是主键值),就没必要在主键索引查找了,因为查询主键索引的 B+ 树的成本会比查询二级索引的 B+ 的成本大,优化器基于查询成本的考虑,会选择查询代价小的普通索引。
            在这里插入图片描述
      • execute 阶段,也就是执行阶段经历完优化器后,就确定了执行方案,接下来 MySQL 就真正开始执行语句了,这个工作是由执行器完成的。在执行的过程中,执行器就会和存储引擎交互了,交互是以记录为单位的。
        • 执行器和存储引擎的交互过程:有三种方式来执行过程
          • 主键索引查询:
            • 比如, select * from product where id = 1;这条查询语句的查询条件用到了主键索引,而且是等值查询,同时主键 id 是唯一,不会有 id 相同的记录,所以优化器决定选用访问类型为 const 进行查询也就是使用主键索引查询一条记录,那么执行器与存储引擎的执行流程是这样的:
              • 执行器第一次查询,会调用 read_first_record 函数指针指向的函数,因为优化器选择的访问类型为 const,这个函数指针被指向为 InnoDB 引擎索引查询的接口,把条件 id = 1 交给存储引擎,让存储引擎定位符合条件的第一条记录
              • 存储引擎通过主键索引的 B+ 树结构定位到 id = 1的第一条记录,如果记录是不存在的,就会向执行器上报记录找不到的错误,然后查询结束。如果记录是存在的,就会将记录返回给执行器
              • 执行器从存储引擎读到记录后,接着判断记录是否符合查询条件,如果符合则发送给客户端,如果不符合则跳过该记录
              • 执行器查询的过程是一个 while 循环,所以还会再查一次,但是这次因为不是第一次查询了,所以会调用 read_record 函数指针指向的函数,因为优化器选择的访问类型为 const,这个函数指针被指向为一个永远返回 - 1 的函数,所以当调用该函数的时候,执行器就退出循环,也就是结束查询了。这个语句也就执行完成了。
          • 全表扫描
            • 比如,select * from product where name = ‘hhb’;这条查询语句的查询条件没有用到索引,所以优化器决定选用访问类型为 ALL 进行查询,也就是全表扫描的方式查询,那么这时执行器与存储引擎的执行流程是这样的:
              • 执行器第一次查询,会调用 read_first_record 函数指针指向的函数,因为优化器选择的访问类型为 all,这个函数指针被指向为 InnoDB 引擎全扫描的接口,让存储引擎读取表中的第一条记录;
              • 执行器会判断读到的这条记录的 name 是不是 hhb,如果不是则跳过;如果是则将记录发给客户的Server 层每从存储引擎读到一条记录就会发送给客户端,之所以客户端显示的时候是直接显示所有记录的,是因为客户端是等查询语句查询完成后,才会显示出所有的记录)。
              • 执行器查询的过程是一个 while 循环,所以还会再查一次,会调用 read_record 函数指针指向的函数,因为优化器选择的访问类型为 all,read_record 函数指针指向的还是 InnoDB 引擎全扫描的接口,所以接着向存储引擎层要求继续读刚才那条记录的下一条记录,存储引擎把下一条记录取出后就将其返回给执行器(Server层),执行器继续判断条件,不符合查询条件即跳过该记录,否则发送到客户端;
              • 一直重复上述过程,直到存储引擎把表中的所有记录读完,然后向执行器(Server层) 返回了读取完毕的信息;
              • 执行器收到存储引擎报告的查询完毕的信息,退出循环,停止查询,然后这个语句就执行完了。
          • 索引下推:索引下推能够减少二级索引在查询时的回表操作,提高查询的效率,因为它将 Server 层部分负责的事情,交给存储引擎层去处理了
            在这里插入图片描述
            • 比如,select * from t_user where age > 20 and reward = 100000;联合索引当遇到范围查询 (>、<、between、like) 就会停止匹配,也就是 a 字段能用到联合索引,但是 reward 字段则无法利用到索引,也就是索引下推没办法使用了呗。
            • 不使用索引下推(MySQL 5.6 之前的版本)时,执行器与存储引擎的执行流程是这样的:
              • Server 层首先调用存储引擎的接口定位到满足查询条件的第一条二级索引记录,也就是定位到 age > 20 的第一条记录;
              • 存储引起根据二级索引的 B+ 树快速定位到这条记录后,获取主键值,然后进行回表操作,将完整的记录返回给 Server 层;
              • Server 层在判断该记录的 reward 是否等于 100000,如果成立则将其发送给客户端;否则跳过该记录;
              • 接着,继续向存储引擎索要下一条记录,存储引擎在二级索引定位到记录后,获取主键值,然后回表操作,将完整的记录返回给 Server 层
              • 如此往复,直到存储引擎把表中的所有记录读完。
            • 没有索引下推的时候,每查询到一条二级索引记录,都要进行回表操作,然后将记录返回给 Server,接着 Server 再判断该记录的 reward 是否等于 100000而使用索引下推后,判断记录的 reward 是否等于 100000 的工作交给了存储引擎层,过程如下 :【使用了索引下推后,虽然 reward 列无法使用到联合索引,但是因为它包含在联合索引(age,reward)里,所以直接在存储引擎过滤出满足 reward = 100000 的记录后,才去执行回表操作获取整个记录。相比于没有使用索引下推,节省了很多回表操作。】
              • Server 层首先调用存储引擎的接口定位到满足查询条件的第一条二级索引记录,也就是定位到 age > 20 的第一条记录;这一步和没用索引下推是一样的。
              • 存储引擎定位到二级索引后,先不执行回表操作,而是先判断一下该索引中包含的列(reward列)的条件(reward 是否等于 100000)是否成立。如果条件不成立,则直接跳过该二级索引。如果成立,则执行回表操作,将完成记录返回给 Server 层
              • Server 层在判断其他的查询条件(本次查询没有其他条件)是否成立,如果成立则将其发送给客户端;否则跳过该记录,然后向存储引擎索要下一条记录。
              • 如此往复,直到存储引擎把表中的所有记录读完。
    • 比如选择索引,join 表的连接顺序
  • 5.验证权限,验证是否有该表的查询权限以及执行权限
    • 没有则返回无权限的错误
    • 有则执行第六步,使用这个数据库引擎提供的接口
  • 6.通过执行器调用存储引擎执行该 sql,然后返回执行结果
    • 也就是去引擎层获取数据返回(如果开启查询缓存则会缓存查询结果)
      在这里插入图片描述
    • MySQL 主要分为 Server 层和存储引擎层:
      • Server 层:主要包括连接器、查询缓存、分析器、优化器、执行器等,所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器、视图,函数等,还有一个通用的日志模块 binlog 日志模块。
      • 存储引擎: 主要负责数据的存储和读取,采用可以替换的插件式架构,支持 InnoDB、MyISAM、Memory 等多个存储引擎,其中 InnoDB 引擎有自有的日志模块 redolog 模块。现在最常用的存储引擎是 InnoDB,它从 MySQL 5.5 版本开始就被当做默认存储引擎了
  • Server层的连接器
    • 每个客户端连接来到Server层之后,都会在Server层中的服务器进程中拥有一个线程,这个连接的相关查询只会在这个单独的线程中执行
      • 该线程只能轮流在某个CPU核心或者CPU中运行
      • 服务器(Server层)会负责缓存线程,所以不需要咱们为每一个新建的连接创建或者销毁线程
        • MySQL 5.5或者更新的版本提供了一个API,支持线程池(Thread-Pooling) 插件,可以使用池中少量的线程来服务大量的连接。
    • 当客户端(应用)连接到MySQL服务器时,服务器需要对其进行认证。认证基于用户名、原始主机信息和密码。如果使用了安全套接字(SSL)的方式连接,还可以使用X.509证书认证。一旦客户端连接成功,服务器会继续验证该客户端是否具有执行某个特定查询的权限(例如,是否允许客户端对world数据库的Country表执行SELECT语句)。
    • MySQL使用文件系统的目录和文件来保存数据库和表的定义,不同的存储引擎保存数据和索引的方式是不同的,但表的定义则是在MySQL服务层统一处理的
      • 在文件系统中,MySQL将每个数据库(也可以称之schema)保存为数据目录下的一个子目录
      • 创建表时,MySQL会在数据库子目录下创建一个和表同名的.frm 文件保存表的定义
  • Server的优化(器)与执行(器)
    • MySQL会解析查询,并创建内部数据结构(解析树),然后对其进行各种优化,包括重写查询、决定表的读取顺序,以及选择合适的索引等。优化器并不关心表使用的是什么存储引擎,但存储引擎对于优化查询是有影响的。优化器会请求存储引擎提供容量或某个具体操作的开销信息,以及表数据的统计信息等,得到之后就可以进行优化了呗
    • 在解析和优化阶段,MySQL将生成查询对应的执行计划,MySQL 的查询执行引擎则根据这个执行计划来完成整个查询。这里执行计划是一个数据结构,而不是和很多其他的关系型数据库那样会生成对应的字节码
    • 相对于查询优化阶段,查询执行阶段不是那么复杂: MySQL只是简单地根据执行计划给出的指令逐步执行。在根据执行计划逐步执行的过程中,有大量的操作需要通过调用存储引擎实现的接口来完成,这些接口也就是我们称为"handler API”的接口。查询中的每一个表由一个handler的实例表示。前面我们有意忽略了这点,实际上,MySQL在优化阶段就为每个表创建了一个handler实例,优化器根据这些实例的接口可以获取表的相关信息,包括表的所有列名、索引统计信息,等等

PART2-2:使用 Innodb 的情况下,一条更新语句是怎么执行的【在实际数据库肯定不会设置年龄这个字段的或者说写死的。其实这条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块是 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志)

update T set c=c+1 where id=2;

在这里插入图片描述
在这里插入图片描述

  • 1.执行器先找引擎取 id=2 这一行。id 是主键,引擎直接用树搜索找到这一行
    • 如果 id=2 这一行所在的数据页本来就在内存中,就直接返回给执行器
      • InnoDB 数据页结构:一个数据页大致划分七个部分:
        • File Header:表示页的一些通用信息,占固定的38字节。
        • page Header:表示数据页专有信息,占固定的56字节。
        • inimum+Supermum:两个虚拟的伪记录,分别表示页中的最小记录和最大记录,占固定的26字节。
        • User Records:真正存储我们插入的数据,大小不固定。
        • Free Space:页中尚未使用的部分,大小不固定。
        • Page Directory:页中某些记录的相对位置,也就是各个槽对应的记录在页面中的地址偏移量。
        • File Trailer:用于检验页是否完整,占固定大小 8 字节。
    • 不在内存中,需要先从磁盘读入内存,然后再返回
  • 2.执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据
  • 3.引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务
  • 4.执行器生成这个操作的 binlog,并把 binlog 写入磁盘
  • 5.执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成

PART3:执行引擎【存储引擎】:MySQL有一个具体管理和处理数据的内部引擎(咱们写SQL代码时不是也经常CREATE TABLE语句全都以ENGINE=InnoDB语句结束嘛)。MySQL与其他DBMS不一样,它具有多种引擎。它打包多个引擎,这些引擎都隐藏在MySQL服务器内,全都能执行CREATE TABLE和SELECT等命令。
在这里插入图片描述

  • MySQL具有多种引擎的原因就是,因为多种引擎具有各自不同的功能和特性,为不同的任务选择正确的引擎能获得良好的功能和灵活性
    • 可以通过 show engines 命令来查看 MySQL 支持的所有存储引擎。
      在这里插入图片描述
    • MySQL 存储引擎介绍(InnoDB、MyISAM、MEMORY):MySQL 支持多种存储引擎,比如 InnoDB,MyISAM,Memory,Archive 等等.在大多数的情况下,直接选择使用 InnoDB 引擎都是最合适的,InnoDB 也是 MySQL 的默认存储引擎
      • InnoDB 是事务型数据库的首选引擎,支持事务安全表 (ACID),支持行锁定和外键。MySQL5.5.5 之后,InnoDB 作为默认存储引擎
        • 所有的存储引擎中只有 InnoDB 是事务性存储引擎,也就是说只有 InnoDB 支持事务。
        • MyISAM 和 InnoDB 的区别有哪些:
          在这里插入图片描述
      • MyISAM 基于 ISAM 的存储引擎,并对其进行扩展。它是在 Web、数据存储和其他应用环境下最常用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务。在 MySQL5.5.5 之前的版本中,MyISAM 是默认存储引擎
      • MEMORY 存储引擎将表中的数据存储到内存中,为查询和引用其他表数据提供快速访问
        • 都说 InnoDB 好,那还要不要使用 MEMORY 引擎?要用,只不过要具体情况具体分析:
          • 内存表就是使用 memory 引擎创建的表
          • 不建议在生产环境上使用内存表。这里的原因主要包括两个方面:
            • 锁粒度问题;
            • 数据持久化问题。
          • 由于重启会丢数据,如果一个备库重启,会导致主备同步线程停止;如果主库跟这个备库是双 M 架构,还可能导致主库的内存表数据被删掉。
  • 存储引擎的选择:可以简单地归纳为-句话:“除非需要用到某些InnoDB不具备的特性,并且没有其他办法可以替代,否则都应该优先选择InnoDB引擎”。
    • 例如,如果要用到全文索引,建议优先考虑InnoDB加上Sphinx的组合,而不是使用支持全文索引的MyISAM。
    • 当然,如果不需要用到InnoDB的特性,同时其他引擎的特性能够更好地满足需求,也可以考虑一下其他存储引擎。举个例子,如果不在乎可扩展能力和并发能力,也不在乎崩溃后的数据丢失问题,却对InnoDB的空间占用过多比较敏感,这种场合下选择MyISAM就比较合适。
    • 引擎类型可以混用。
      • 混用引擎类型有一个大缺陷。外键(用于强制实施引用完整性)不能跨引擎,即使用一个引擎的表不能引用具有使用不同引擎的表的外键除非万不得已,否则建议不要混合使用多种存储引擎,否则可能带来一系列复杂的问题。
        • 尽量不要在同一个事务中使用多种存储引擎,MySQL服务器层不管理事务,事务是由下层的存储引擎实现的。如果在事务中混合使用了事务型和非事务型的表(例如InnoDB和MyISAM表),在正常提交的情况下不会有什么问题。但如果该事务需要回滚,非事务型的表上的变更就无法撤销,这会导致数据库处于不一致的状态,这种情况很难修复,事务的最终结果将无法确定。所以,为每张表选择合适的存储引擎非常重要。
      • 存储引擎具体的选择标准如下
        • 如果无法确定要用哪个引擎,那么就使用InnoDB,这个默认选项是安全的,尤其是搞不清楚具体需要什么的时候。
          • 需要用到事务支持&&需要在线热备份&&只读或者大部分只读的表,选InnoDB,比如订单处理
        • 事务:如果应用需要事务支持(如果涉及订单处理,那么支持事务就是必要选项。半完成的订单是无法用来吸引用户的。另外一个重要的考虑点是存储引擎对外键的支持情况。InnoDB是订单处理类应用的最佳选择。),那么InnoDB (或者XtraDB)是目前最稳定并且经过验证的选择。如果不需要事务,并且主要是SELECT和INSERT操作,那么MyISAM是不错的选择。一般日志型的应用比较符合这一特性。
          • 假设你需要实时地记录一台中心电话交换机的每一通 电话的日志到MySQL中,或者通过Apache的mod_ log_ sql 模块将网站的所有访问信息直接记录到表中。这一类应用的插入速度有很高的要求,数据库不能成为瓶颈。MyISAM或者Archive存储引擎对这类应用比较合适,因为它们开销低,而且插入速度非常快。如果需要提要求,要对记录的日志做分析报表,生成报表的SQL很有可能会导致插入效率明显降低,这时候该怎么办?,有两种解决办法:
            • 一种解决方法是 利用MySQL内置的复制方案将数据复制一份到备库,然后在备库上执行比较消耗时间和CPU的查询。这样主库只用于高效的插入工作,而备库上执行的查询也无须担心影响到日志的插入性能。当然也可以在系统负载较低的时候执行报表查询操作,但应用在不断变化,如果依赖这个策略可能以后会导致问题。
            • 另外一种方法,在日志记录表的名字中包含年和月的信息,比如web logs 2012 01或者web_ logs_ 2012 jan。 这样可以在已经没有插入操作的历史表上做频繁的查询操作,而不会干扰到最新的当前表上的插入操作
          • 有些表的数据用于编制类目或者分列清单(如工作岗位、竟拍、不动产等),这种应用场景是典型的 读多写少的业务。如果不介意MyISAM的崩溃恢复问题,选用MyISAM引擎是合适的
            • 一般日志型的应用,主要是SELECT和INSERT操作那么选MyISAM
        • 备份:备份的需求也会影响存储引擎的选择。如果可以定期地关闭服务器来执行备份,那么备份的因素可以忽略。反之,如果需要在线热备份,那么选择InnoDB就是基本的要求
        • 崩潰恢复:数据量比较大的时候,系统崩溃后如何快速地恢复是一个需要考虑的问题。相对而言,MyISAM崩溃后发生损坏的概率比InnoDB要高很多,而且恢复速度也要慢。因此,即使不需要事务支持,很多人也选择InnoDB引擎,这是一个非常重要的因素
        • 特有的特性:有些应用可能依赖一些存储引擎所独有的特性或者优化,比如很多应用依赖聚簇索引的优化。另外,MySQL中也只有MyISAM支持地理空间搜索。如果一个存储引擎拥有一些关键的特性,同时却又缺乏一些必要的特性,那么有时候不得不做折中的考虑,或者在架构设计上做一些取舍。某些存储引擎无法直接支持的特性,有时候通过变通也可以满足需求。
        • MySQL支持,MyISAM、 InnoDB(1.2版本)和Sphinx存储引擎都支持全文索引。
    • 当咱们使用CREATE TABLE语句时,该引擎具体创建表
    • 当咱们使用SELECT语句或进行其他数据库处理时,该引擎在内部处理你的请求
  • Mysql执行引擎(mysql默认用InnoDB,Mysql最重要最与众不同的特点是他的存储引擎架构,这种架构的设计将查询处理(Query Processing)及其他系统任务(Server Task)和数据的存储、提取相分离。分离后就可以在使用时根据性能、特性以及其他需求来选择数据存储的方式):MySQL 支持多种存储引擎,比如 InnoDB,MyISAM,Memory,Archive 等等,每种Mysql存储引擎都可以实现自己的锁策略和锁粒度
    • MySQL 存储引擎架构:
      • MySQL 存储引擎采用的是插件式架构,支持多种存储引擎我们甚至可以为不同的数据库表设置不同的存储引擎以适应不同场景的需要。存储引擎是基于表的,而不是数据库
      • 并且,你还可以根据 MySQL 定义的存储引擎实现标准接口来编写一个属于自己的存储引擎。MySQL 官方文档也有介绍到如何编写一个自定义存储引擎。这些非官方提供的存储引擎可以称为第三方存储引擎,区别于官方存储引擎。像目前最常用的 InnoDB 其实刚开始就是一个第三方存储引擎,后面由于过于优秀,其被 Oracle 直接收购了
    • MYSQL提供的两种事务型的存储引擎:
      在这里插入图片描述
    • mysql默认用InnoDB存储引擎,那InnoDB 是如何存储数据的:
      • 记录是按照行来存储的,但是数据库的读取并不以行为单位,否则一次读取(也就是一次 I/O 操作)只能处理一行数据,效率会非常低。
      • 因此,为了防止效率底下,InnoDB 的数据是按数据页为单位来读写的【数据库的 I/O 操作的最小单位是页】,也就是说,当需要读一条记录的时候,并不是将这个记录本身从磁盘读出来,而是以页为单位,将其整体读入内存
        • 数据页:InnoDB 数据页的默认大小是 16KB,意味着数据库每次读写都是以 16KB 为单位的,一次最少从磁盘中读取 16K 的内容到内存中,一次最少把内存中的 16K 内容刷新到磁盘中。
          • 数据页结构”
            在这里插入图片描述
          • 数据页中的页目录:
            在这里插入图片描述
            • InnoDB 是如何给记录创建页目录的呢
              在这里插入图片描述
              在这里插入图片描述
  • 文件系统中MYSQL将每个DB保存为数据目录下的一个子文件夹。)创建表时,MYSQL会在此数据库子目录下创建一个和表同名的.frm文件保存表的定义
    在这里插入图片描述
    这里就可以看看Mysql新建一个数据库时发生了什么
    在这里插入图片描述
  • 常见的执行引擎分类:
    在这里插入图片描述
    • 由于MySQL数据库开源特性,存储引擎可以分为MySQL官方存储引擎和第三方存储引擎。有些第三方存储引擎很强大,如大名鼎鼎的InnoDB存储引擎(最早是第三方存储引擎,后被Oracle收购),其应用就极其广泛,甚至是MySQL数据库OLTP(Online Transaction Processing在线事务处理)应用中使用最广泛的存储引擎(InnoDB存储引擎是OLTP应用中核心表的首选存储引擎)。还是那句话,应该根据具体的应用选择适合的存储引擎
    • InnoDB:InnoDB是一个可靠的事务处理引擎(支持事务),它不支持全文本搜索
      在这里插入图片描述
      • InnoDB的体系架构:
        • 后台线程:负责刷新内存池中的数据,保证缓冲池中的内存缓存的是最新或者最近的数据。此外将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下InnoDB能恢复到正常运行状态。InnoDB存储引擎是多线程的模型,因此其后台有多个不同的后台线程,负责处理不同的任务。常见的后台线程如下:
          • Master Thread:MasterThread是一个非常核心的后台线程,主要负责将缓冲池中的数据异步刷新到磁盘,保证数据的一致性,包括脏页的刷新、合并插人缓冲(INSERT BUFFER)、UNDO页的回收等。
          • IO Thread:主要负责这些IO请求的回调(call back)处理
            • 在InnoDB存储引擎中大量使用了AIO来处理写IO请求来提高数据库的性能。
          • Purge Thread:事务被提交后,事务使用的undolog可能不再需要,所以需要使用PurgeThread来回收已经使用并分配的undo页。
          • Page Cleaner Thread:将之前版本中脏页的刷新操作都放入到单独的线程中来完成,减轻查询线程的阻塞。
        • 内存池:(由InnoDB存储引擎中的多个内存块组成),可以视为一个基于磁盘的数据库系统,一般使用缓冲池技术来提高数据库的整体性能。
          • 1.维护所有进程/线程需要访问的多个内部数据结构。
          • 2.缓存磁盘上的数据,方便快速地读取,同时在对磁盘文件的数据修改之前在这里,缓存。
          • 3.重做日志(redo log)缓冲。等,不止这些哦。
      • InnoDB存储引擎设计目标主要面向在线事务处理(OLTP)的应用
        在这里插入图片描述
      • InnoDB存储引擎的特点是
        • 行锁设计
        • 支持外键
        • 并支持类似于Oracle的提供一致性非锁定读,即默认读取操作不会产生锁。从MySQL数据库5.5.8版本开始,InnoDB 存储引擎是默认的存储引擎。
        • 同时被设计用来最有效的利用或者使用内存和CPU
      • InnoDB是MySQL的默认事务型引擎,也是最重要、使用最广泛的存储引擎。它被设计用来处理大量的短期(short-lived) 事务短期事务大部分情况是正常提交的很少会被回滚InnoDB的性能和自动崩溃恢复特性,使得它在非事务型存储的需求中也很流行除非有非常特别的原因需要使用其他的存储引擎,否则应该优先考虑InnoDB引擎
      • InnoDB采用MVCC来支持高并发,并且实现了四个标准的隔离级别。其默认级别是REPEATABLE READ (可重复读),并且通过间隙锁(next-key locking)策略防止幻读的出现间隙锁使得InnoDB不仅仅锁定查询涉及的行,还会对索引中的间隙进行锁定,以防止幻影行的插入
      • 除此之外,InnoDB 储存引擎还提供了插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead)等高性能和高可用的功能
      • InnoDB的数据存储在表空间(tablespace) 中,表空间是由InnoDB管理的一个黑盒子,由一系列的数据文件组成。在MySQL 4.1以后的版本中,InnoDB可以将每个表的数据和索引存放在单独的文件中。InnoDB也可以使用裸设备作为表空间的存储介质
        • 对于表中数据的存储,InnoDB 存储引擎采用了聚集(clustered) 的方式,因此每张表的存储都是按主键的顺序进行存放。如果没有显式地在表定义时指定主键,InnoDB 存储引擎会为每一行生成一个6字节的ROWID,并以此作为主键
    • MyISAM:MyISAM是一个性能极高的引擎,MyISAM提供了大量的特性,包括全文索引、压缩、空间函数(GIS)等,但MyISAM不支持事务和行级锁,支持表锁设计、全文索引等,而且有一个毫无疑问的缺陷就是崩溃后无法安全恢复。正是由于MyISAM引擎的缘故
      在这里插入图片描述
      • 但是对于只读的数据,或者表比较小、可以忍受修复(repair) 操作,则依然可以继续使用MyISAM (但请不要默认使用MyISAM,而是应当默认使用InnoDB)。
      • MyISAM会将表存储在两个文件中:数据文件和索引文件,分别以. MYD和.MYI为扩展名。MyISAM表可以包含动态或者静态(长度固定)行。MySQL会根据表的定义来决定采用何种行格式。MyISAM 表可以存储的行记录数,一般受限于可用的磁盘空间,或者操作系统中单个文件的最大尺寸。
      • 在很多我们已知的场景中,InnoDB 的速度都可以让MyISAM望尘莫及,尤其是使用到聚簇索引,或者需要访问的数据都可以放入内存的应用。
      • MyISAM特性:
        • 加锁与并发MyISAM对整张表加锁,而不是针对行,也就是支持表锁设计读取时会对需要读到的所有表加共享锁写入时则对表加排他锁。但是在表有读取查询的同时,也可以往表中插入新的记录(这被称为并发插入,CONCURRENT INSERT)。
        • 修复:对于MyISAM表,MySQL可以手工或者自动执行检查和修复操作,但这里说的修复和事务恢复以及崩溃恢复是不同的概念。执行表的修复可能导致一些数据丢失,而且修复操作是非常慢的。可以通过CHECK TABLE mytable 检查表的错误,如果有错误可以通过执行REPAIR TABLE mytable 进行修复。另外,如果MySQL服务器已经关闭,也可以通过myisamchk命令行工具进行检查和修复操作。
        • 索引特性:对于MyISAM表,即使是BLOB和TEXT等长字段,也可以基于其前500个字符创建索引。MyISAM也支持全文索引,这是一种基于分词创建的索引,可以支持复杂的查询。
        • 延迟更新索引键(Delayed Key Write):创建MyISAM表的时候,如果指定了DELAY_ KEY_ WRITE选项,在每次修改执行完成时,不会立刻将修改的索引数据写人磁盘,而是会写到内存中的键缓冲区(in-memory key buffer),只有在清理键缓冲区或者关闭表的时候才会将对应的索引块写人到磁盘。这种方式可以极大地提升写入性能,但是在数据库或者主机崩溃时会造成索引损坏,需要执行修复操作。延迟更新索引键的特性,可以在全局设置,也可以为单个表设置。
          • MyISAM存储引擎的另一个与众不同的地方是它的缓冲池只缓存(cache) 索引文件,而不缓冲数据文件,这点和大多数的数据库都非常不同。
      • MYISAM(节约空间、速度快)与INNODB(安全性高、支持事务、可多表多用户操作)比较
        在这里插入图片描述
        • 虽然MyISAM 的性能还行,各种特性也还不错(比如全文索引、压缩、空间函数等)。但是,MyISAM 不支持事务和行级锁,而且最大的缺陷就是崩溃后无法安全恢复
          • InnoDB 提供事务支持,实现了 SQL 标准定义了四个隔离级别,具有提交(commit)和回滚(rollback)事务的能力。并且,InnoDB 默认使用的 REPEATABLE-READ(可重读)隔离级别是可以解决幻读问题发生的(基于 MVCC 和 Next-Key Lock)
          • 使用 InnoDB 的数据库在异常崩溃后,数据库重新启动的时候会保证数据库恢复到崩溃前的状态。这个恢复的过程依赖于 redo log
            • Innodb 有redolog日志文件,MyISAM 没有
        • InnoDB支持行级锁(row-level locking)和表级锁,默认为行级锁【行级锁的粒度更小,行级锁仅对相关的记录上锁即可(对一行或者多行记录加锁),所以对于并发写入操作来说, InnoDB 的性能更高。】,而MyISAM支持表级锁【MyISAM 只有表级锁(table-level locking)锁,点点这里看更多哦
          • 这也是为什么 InnoDB 在并发写的时候,性能更牛皮了!你MyISAM动不动就锁住整张表,只有那几行在操作,其他行都被锁住了,想操作也操作不了,根本不行
          • MyISAM 连行级锁都不支持就更别提MVCC了。MVCC 可以看作是行级锁的一个升级,可以有效减少加锁操作,提高性能。你看MyISAM傻不傻
        • InnoDB是聚集索引,使用B+Tree作为索引结构,数据文件是和索引绑在一起的【InnoDB 引擎中其数据文件本身就是索引文件】,必须要有主键。MyISAM是非聚集索引,也是使用B+Tree作为索引结构,索引和数据文件是分离的索引保存的是数据文件的指针,树的叶节点 data 域保存了完整的数据记录。主键索引和辅助索引是独立的。
        • Innodb存储文件有frm、ibd,而Myisam是frm、MYD、MYI
          • Innodb:frm是表定义文件,ibd是数据文件
          • Myisam:frm是表定义文件,myd是数据文件,myi是索引文件
        • InnoDB 必须有唯一索引(主键),如果没有指定的话 InnoDB 会自己生成一个隐藏列Row_id来充当默认主键,MyISAM 可以没有
    • MEMORY:MEMORY在功能等同于MyISAM,但由于数据存储在内存(不是磁盘)中速度很快(特别适合于临时表);如果需要快速地访问数据,并且这些数据不会被修改,重启以后丢失也没有关系,那么使用Memory表(以前也叫做HEAP表)是非常有用的。Memory表至少比MyISAM表要快一个数量级,因为所有的数据都保存在内存中,不需要进行磁盘I/O。Memory表的结构在重启以后还会保留,但数据会丢失
      • Memory表支持Hash索引,因此查找操作非常快。虽然Memory表的速度非常快,但还是无法取代传统的基于磁盘的表。Memroy 表是表级锁,因此并发写入的性能较低。它不支持BLOB或TEXT类型的列,并且每行的长度是固定的,所以即使指定了VARCHAR列,实际存储时也会转换成CHAR,这可能导致部分内存的浪费(其中一些限制在Percona版本已经解决)。如果MySQL在执行查询的过程中需要使用临时表来保存中间结果,内部使用的临时表就是Memory表。如果中间结果太大超出了Memory 表的限制,或者含有BLOB或TEXT字段,则临时表会转换成MyISAM表。
        • MySQL 临时表的用法和特性:
          • 只对当前session可见。
          • 可以与普通表重名。
          • 增删改查用的是临时表。
          • show tables 不显示普通表。
          • 在实际应用中,临时表一般用于处理比较复杂的计算逻辑。
          • 由于临时表是每个线程自己可见的,所以不需要考虑多个线程执行同一个处理时临时表的重名问题,在线程退出的时候,临时表会自动删除。
      • Memroy表在很多场景可以发挥好的作用:
        • 用于查找(lookup)或者映射(mapping) 表,例如将邮编和州名映射的表。
        • 用于缓存周期性聚合数据(periodically aggregated data)的结果。
        • 用于保存数据分析中产生的中间数据。
    • CSV引擎:CSV引擎可以将普通的CSV文件(逗号分割值的文件)作为MySQL的表来处理,但这种表不支持索引。CSV引擎可以在数据库运行时拷入或者拷出文件。可以将Excel 等电子表格软件中的数据存储为CSV文件,然后复制到MySQL数据目录下,就能在MySQL中打开使用。同样,如果将数据写人到一个CSV引擎表,其他的外部程序也能立即从表的数据文件中读取CSV格式的数据。因此**CSV引擎可以作为一种数据交换的机制,非常有用**。
  • 可以用这条命令来转换表的引擎:ALTER TABLE mytable ENGINE=InnoDB;
    在这里插入图片描述
//可以使用SHOW TABLE STATUS 命令(在MySQL 5.0以后的版本中,也可以查询INFORMATION_ SCHEMA 中对应的表)显示表的相关信息。例如,对于mysql数据库中的user表:
SHOW TABLE STATUS LIKEuser’ \G

在这里插入图片描述

  • 转换表的引擎的三种方法:
    • 使用ALTER TABLE语句:mysq1> ALTER TABLE mytable ENGINE = InnoDB;
      • ALTER TABLE语法可以适用任何存储引擎。但有一个问题:需要执行很长时间。MySQL会按行将数据从原表复制到一张新的表中,在复制期间可能会消耗系统所有的I/O能力,同时原表上会加上读锁。所以,在繁忙的表上执行此操作要特别小心。
        • 一个替代方案是采用接下来的导出与导入的方法,手工进行表的复制。如果转换表的存储引擎,将会失去和原引擎相关的所有特性。例如,如果将一张InnoDB表转换为MyISAM,然后再转换回InnoDB,原InnoDB表上所有的外键将丢失。
    • 导出与导入:为了更好地控制转换的过程,可以使用mysqldump工具将数据导出到文件,然后修改文件中CREATE TABLE语句的存储引擎选项,注意同时修改表名,因为同一个数据库中不能存在相同的表名,即使它们使用的是不同的存储引擎。同时要注意mysqldump默认会自动在CREATE TABLE语句前加上DROP TABLE语句,不注意这一点可能会导致数据丢失
    • 第三种转换的技术综合了第一种方法的高效和第二种方法的安全。不需要导出整个表数据,而是先创建一个新的存储引擎的表,然后利用INSET…SELECT语法来导数据:
mysql> CREATE TABLE innodb table LIKE myisam table;
mysql> ALTER TABLE innodb table ENGINE=InnoDB;
mysq1> INSERT INTO innodb table SELECT * FROM myisam table;
  • 如果让咱们自己设计一个Key-Value存储引擎(Design a key-value store)怎么搞。当然这个咱们只是理一下思路,这个要讲深的话也确实很深。【数据库往往是一个比较丰富完整的系统, 提供了SQL查询语言,事务和水平扩展等支持。存储引擎则是小而精, 纯粹专注于单机的读/写/存储。一般来说, 数据库底层往往会使用某种存储引擎。】
    在这里插入图片描述
    • LevelDB整体结构梳理:
      • 内存随机写甚至比硬盘的顺序读还要慢,磁盘随机写就更慢了,说明我们要避免随机写,最好设计成顺序写因此好的KV存储引擎,都在尽量避免更新操作,把更新和删除操作转化为顺序写操作 。LevelDB采用了一种SSTable的数据结构来达到这个目的。
        • SSTable(Sorted String Table)就是一组按照key排序好的 key-value对, key和value都是字节数组。SSTable既可以在内存中,也可以在硬盘中。SSTable底层使用LSM Tree(Log-Structured Merge Tree)来存放有序的key-value对
      • LevelDB整体由如下几个组成部分:
        在这里插入图片描述
        在这里插入图片描述
        • Manifest文件:Manifest文件记录各个SSTable各个文件的管理信息,比如该SST文件处于哪个Level,文件名称叫啥,最小key和最大key各自是多少
        • Log文件:Log文件主要作用是系统发生故障时,能够保证不会丢失数据。因为在数据写入内存中的MemTable之前,会先写入Log文件,这样即使系统发生故障,MemTable中的数据没有来得及Dump到磁盘,LevelDB也可以根据log文件恢复内存中的MemTable,不会造成系统丢失数据。这个方式就叫做 WAL(Write Ahead Log),很多传统数据库例如MySQL也使用了WAL技术来记录日志
        • MemTable:MemTable 是内存中的数据结构,存储的内容跟硬盘上的SSTable一样,只是格式不一样。Immutable MemTable的内存结构和Memtable是完全一样的,区别仅仅在于它是只读的,而MemTable则是允许写入和读取的。当MemTable写入的数据占用内存到达指定大小,则自动转换为Immutable Memtable,等待Dump到磁盘中,系统会自动生成一个新的MemTable供写操作写入新数据
          在这里插入图片描述

巨人的肩膀:
高性能MySQL
mysql技术内幕
巨人的肩膀:https://www.javalearn.cn
B站各位大佬
小林coding

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值