• 第02篇_Mysql

    第01章_MySql概述

    第一节 MySql简介

    1. 什么是MySql?

    MySQL是一个开源的关系型数据库管理系统(RDBMS) ,主要应用在互联网WEB领域。

    发展历程简述如下:

    扩展:

    1. MySQL6.x 版本之后分为 社区版 和 商业版。

    2. MySQL 的创造者担心 MySQL 有闭源的风险,因此创建了 MySQL 的分支项目 MariaDB

     

     

    第二节 安装部署

     

    1. Windwos版本安装

    详见部署文档!

     

    2. Linux版本安装

    详见部署文档!

     

    3. 远程访问配置

     

    4. 错误日志

    错误日志默认存放在 /var/log/mysqld.log,记录了 mysqld 启动和停止,以及服务器在运行过程中产生的错误信息。

     

     

    第三节 客户端

    1. 命令行客户端

    注意:

    1. 将MySql的bin路径(如:D:\MySql\mysql-8.0.22-winx64\bin)配置到PATH变量。

     

    2. 其它客户端

     

     

    第四节 体系结构

    1. Mysql软件架构

    image-20231114191426279

     

    2. 存储引擎介绍

    存储引擎数据存储和提取的核心,插件式的存储引擎架构,使得MySql可以应用在多种不同场景中,并发挥良好作用。

     

    1) 指定存储引擎

    存储引擎是表级别的,也称为表类型,一般在创建表时指定,如未指定则为当前数据库的默认存储引擎。

     

    2) 存储引擎特点
     InnoDBMyISAMMemory
    存储限制64TB
    事务安全支持  
    锁机制行锁表锁表锁
    B+tree索引支持支持支持
    Hash索引  支持
    全文索引支持(5.6+)支持 
    空间使用N/A
    内存使用中等
    并发访问速度
    批量插入速度
    支持外键支持  
    存储文件xxx.ibd:表结构、数据、索引文件
    (二进制数据,可通过ibd2sdi提取表结构)
    xxx.sdi:存储表结构信息
    xxx.MYD:存储数据
    xxx.MYI:存储索引
    xxx.sdi:存储表结构信息

     

    3) 存储引擎选择

    在选择存储引擎时,应根据应用系统的特点选择合适的存储引擎。对于复杂的应用系统,可以根据实际情况选择多种存储引擎进行组合:

     

    3. 二进制日志

    二进制日志(BINLOG)记录了所有的 DDL语句DML语句,但不包括DQL语句,主要用于主从复制灾难时的数据恢复

     

    1) BINLOG格式

    MySQL服务器中提供了多种格式来记录二进制日志,具体格式及特点如下:

    日志格式含义
    STATEMENT基于SQL语句的日志记录,记录的是SQL语句,对数据进行修改的SQL都会记录在日志文件中。
    ROW基于行的日志记录,记录的是每一行的数据变更。(默认)
    MIXED混合了STATEMENT和ROW两种格式,默认采用STATEMENT,在某些特殊情况下会自动切换为ROW进行记录。

    注意:

    1. 如果要修改BINLOG的日志格式,需要在 /etc/my.cnf 中配置 binlog_format 参数并重启服务器。

     

    2) 查看BINLOG

    BINLOG是以二进制方式存储的,不能直接读取,需要通过二进制日志查询工具 mysqlbinlog 来查看。

     

    3) 删除BINLOG

    对于比较繁忙的业务系统,每天生成的binlog数据巨大,如果长时间不清除,将会占用大量磁盘空间。可以通过以下几种方式清理日志:

    指令含义
    reset master删除全部 binlog 日志,删除之后,日志编号将从 binlog.000001重新开始
    purge master logs to 'binlog.*'删除 * 编号之前的所有日志
    purge master logs before 'yyyy-mm-dd hh24:mi:ss'删除日志为 "yyyy-mm-dd hh24:mi:ss" 之前产生的所有日志

    也可以在mysql的配置文件中配置二进制日志的过期时间,设置了之后,二进制日志过期会自动删除。

    第02章_实例管理

    第一节 数据库

    1. 查询和选中数据库

     

    2. 创建数据库

     

    3. 删除数据库

     

    4. 系统数据库

    Mysql数据库安装完成后,自动创建下面四个数据库:

    数据库用途
    mysql存储MySQL服务器正常运行所需要的各种信息 (时区、主从、用户、权限等)
    information_schema提供了访问数据库元数据的各种表和视图,包含数据库、表、字段类型及访问权限等
    performance_schema为MySQL服务器运行时状态提供了一个底层监控功能,主要用于收集数据库服务器性能参数
    sys包含了一系列方便 DBA 和开发人员利用 performance_schema性能数据库进行性能调优和诊断的视图

     

     

     

    第二节 用户

    1. 查询用户信息

     

    2. 修改用户信息

     

    第三节 权限

    1. 查询权限信息

     

    2. 授权与回收

     

     

    第四节 事务

    1. 事务控制命令

     

     

    第五节 锁

    1. 全局锁

    1) 全局锁简介

    全局锁就是对整个数据库加锁,加锁后数据库处于只读状态,后续的DML语句和DDL语句,以及尚未提交的事务都将会被阻塞。

    其典型的应用场景就是做全库的逻辑备份,先对所有的表进行锁定,然后获取全局事务快照,从而保证数据的业务准确性。

    扩展:为什么全库逻辑备份,需要加全局锁呢?

    1. 例如我们有库存表和订单表,在备份库存表后,将要备份订单表时,客户下单,在同一个事务扣减库存,并新增订单。

    2. 当未加全局锁时,库存表备份的是该事务之前的数据,但订单表备份是该事务提交之后的数据,库存和订单就对不上了。

    3. 但如果加了全局锁,在备份库存表前,已经获取到了全局事务快照,即使有新订单,也不会进行备份,保证数据一致性。

     

    2) 全局加锁和解锁

    注意:

    1. 上述操作流程仅作参考,实际上,mysqldump备份时会自动加全局锁,无需手动添加。

    2. 默认情况下,mysqldump在整个备份过程中,都将无法执行写操作,造成业务停摆。

    3. 可以通过添加--single-transaction参数,让它仅在生成全局事务快照时加锁,并且也能保证数据一致性。

     

     

    2. 表级锁

    表级锁即对整张表加锁,容易发生锁冲突,并发性能较低。表级锁可分为表锁、元数据锁(DML)、意向锁。

     

    1) 表锁

     

    2) 元数据锁

    元数据锁(DML)即对表结构加锁,当执行DQL或DML操作时,将会加读锁,当执行DDL语句时,将会加写锁,可通过如下SQL语句查看:

    常见SQL操作加的元数据锁如下:

    SQL操作锁类型说明
    lock tables xxxx readSHARED_READ_ONLY 
    lock tables xxxx writeSHARED_NO_READ_WRITE 
    select、select ... lock in share modeSHARED_READ可兼容SHARED_READ和SHARED_WRITE
    insert 、update、delete、select ... for updateSHARED_WRITE可兼容SHARED_READ和SHARED_WRITE
    alter tableEXCLUSIVE对所有的元数据锁(MDL)都互斥

     

    3) 意向锁

    意向锁用于优化表锁的加锁操作,当未引入意向锁时,如果要加表锁,则必须逐行检查每一行数据,防止与行锁冲突。

    当引入意向锁后,SQL操作在加行锁的同时,也会在表级加意向锁,后续若要添加表锁,只需与表级的意向锁判断兼容性即可。

    SQL操作意向锁类型表锁兼容性
    select ... lock in share mode意向共享锁(IS)表锁-READ可兼容;表锁-WRITE不兼容
    insert、update、delete、select...for update意向排他锁(IX)表锁-READ和表锁-WRITE都不兼容

    查询意向锁的SQL语句如下:

    注意:

    1. 普通select语句并不会添加意向锁,只有特殊的select语句才会加 IS 锁或 IX 锁。

    2. 意向锁之间,即使是 IX 锁和 IX 锁,也不会相互排斥

     

     

    3. 行级锁

    1) 行级锁简介

    在InnoDB引擎中,通过对索引加锁,实现了行级锁效果,常见SQL语句所加的行级锁如下:

    SQL操作行级锁类型说明
    SELECT不加锁 
    SELECT ... LOCK IN SHARE MODE行锁-READ 
    SELECT ... FOR UPDATE行锁-WRITE 
    INSERT、UPDATE、DELETE行锁-WRITE 

    注意:

    1. InnoDB引擎是对索引加锁,而非对记录加锁,如果SQL未走索引,则会对整个表加表锁

    2. 在Oracle中,行级锁仅支持写模式加锁,不支持读模式加锁,而InnoDB引擎都支持。

    查询行级锁及相关的意向锁SQL如下:

    根据不同的事务隔离级别和SQL索引情况,行级锁又分如下:

     

    2) 加锁流程

    在RR隔离级别下,默认使用临键锁(NextKeyLock)扫描,以防止幻读。

    注意:

    1. 间隙锁唯一目的是防止其他事务在间隙插入新记录。

    2. 间隙锁可以共存,一个事务采用的间隙锁不会阻止另一个事务在同一间隙上采用间隙锁(即可以对同一个间隙进行UPDATE)。

     

    3) 示例说明

     

     

    第六节 备份恢复

    1. mysqldump

    mysqldump 是 MySQL 自带的逻辑备份工具。备份时将数据库转换为SQL脚本文件,恢复时通过执行脚本来进行恢复。执行流程如下:

     

    2. mydumper

    mydumper是一款社区开源的MySql逻辑备份和恢复工具,主要有以下几点特性:

    它的官网地址为:https://launchpad.net/mydumperGitHub,GITHUB地址为:https://github.com/maxbube/mydumper,安装步骤如下:

    下面是一些常见的使用场景:

    详细参数说明如下:

    img

     

    3. select… into outfile

    select… into outfile 是MySQL支持的备份恢复命令。备份时将SELECT查询的结果集转换为CVS格式文件,恢复时从CVS文件读取。

     

    4. Xtrabackup

    Xtrabackup是由percona开源的免费数据库热备份软件,它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞的备份(对于MyISAM的备份同样需要加表锁);

    Xtrabackup安装完成后有4个可执行文件,其中2个比较重要的备份工具是 innobackupex、xtrabackup。

    备份开始时首先会开启一个后台检测进程,实时检测 redo log 的变化,一旦发现有新的日志写入,立刻将日志记入后台日志文件xtrabackup_log 中,之后复制innodb的数据文件和系统表空间文件ibdatax,复制结束后,将执行flush tables with readlock,然后复制.frm MYI MYD等文件,最后执行unlock tables,最终停止xtrabackup_log。

     

    5. 性能对比

    在 MySql8.0 环境下同机备份100万CUACCT_LOG结果如下:

    备份方式备份时间备份文件大小恢复时间
    mysqldump8s264M45s
    mydumper6s265M41s
    select… into outfile4.5s220M41s

     

    第03章_数据对象

    第一节 数据类型

    1. 数值类型

    类型大小补充说明
    TINYINT1byte 
    SMALLINT2bytes 
    INT/INTEGER4bytes特殊示例: int(d) zerofill,其中d表示显示宽度(默认11),zerofill表示用0填充。
    BIGINT8bytes 
    FLOAT4bytes 
    DOUBLE8bytes 
    DECIMAL(p,s) 精确小数。其中p表示最大有效数字,s表示最大小数位数,p-s就是最大整数位数。

     

    2. 字符串类型

    类型大小补充说明
    CHAR0-255bytes定长字符串(默认以空格填充)
    VARCHAR0-65535bytes变长字符串
    BLOB0-65535bytes二进制形式的长文本数据
    LONGBLOB0-4294967295bytes二进制形式的极大文本数据

    注意:

    1. CHAR类型字段存储时在右侧填充空格以达到指定的长度,在检索时去掉右边所有空格

    2. VARCHAR类型字段存储时右边不会填充空格,且在检索数据时,会保留数据尾部的空格。

     

    3. 日期时间类型

    类型大小补充说明
    DATE3bytesYYYY-MM-DD
    TIME3bytesHH:MM:SS
    YEAR1bytesYYYY(1901-2155)
    DATETIME8bytesYYYY-MM-DDHH:MM:SS
    TIMESTAMP4bytesYYYY-MM-DDHH:MM:SS(1970-01-01 00:00:01 至 2038-01-19 03:14:07)

    注意:

    1. TIMESTAMP底层以时间戳方式存储,在存储和查询时都要进行时区转换,不同时区对同一数据可能看到不同展示。

    2. DATETIME存储和查询始终以插入时当地的时区为准,其他时区的人查看数据可能会有误差。

     

    第二节 数据表

    1. 查询表信息

     

    2. 创建和删除表

    提示:

    1. 如果出现关键字冲突,可以使用着重号(`)框起来。

     

    3. 修改表结构

     

     

    第三节 约束

    1. 添加约束

    注意:

    1. 自增列关键字AUTO_INCREMENT必须加在整数类型的主键列唯一索引列之上,且最多存在1个

    2. MySQL 8.0之后将自增列的计数器持久化到重做日志中,重启数据库不会再生成已删除的重复序号。

    3. 主表dept必须先创建成功,然后才能创建emp表,指定外键成功,删除表时,先删除从表emp,再删除主表dept。

     

    2. 查看和删除约束

     

     

    第四节 索引

    1. 索引简介

    索引(index)是帮助MySQL高效获取数据的结构,有利于提高数据检索和排序的效率,降低数据库的IO/CPU成本,但是索引也会占用一定的空间,并且在执行DML语句时需对其进行维护。

    在MySQL数据库中,将索引按功能类型分为主键索引唯一索引普通索引全文索引等。

    功能类型关键字特点说明
    主键索引PRIMARY针对表中主键创建的唯一性非空索引,默认创建,且只能有一个
    唯一索引UNIQUE针对表中具有唯一性特征的列建立的索引,可以保证列值的唯一性,但不能保证非空
    普通索引有利于快速检索和排序数据
    全文索引FULLTEXT类似于ElasticSearch中的倒排索引,用于查找文本中的关键词

     

     

    2. 索引语法

     

     

    第五节 视图

    1. 视图语法

     

    2. 检查选项

    Mysql支持通过视图来执行DML操作,但可能出现修改到视图查询之外的行的情况,此时,可添加WITH CHECK OPTION子句来做检查。

    该子句有两种模式:

    注意:

    1. 必须保证视图和表中的数据是一对一的关系,若包含DISTINCT、聚合函数、Group By、Union等,则不可执行DML操作。

     

     

    第六节 序列

    1. 序列语法

     

    第七节 分区表

    1. 分区表语法

     

    第04章_数据操作

    基本SQL语法另请查阅《Oracle学习笔记(基础篇).md》,不再重复介绍。

    第一节 数据修改

    1. 批量插入

     

    2. 归并数据

     

    3. 相关修改

     

     

     

    第二节 数据查询

    1. 分页查询

     

    2. 表达式

    注意:

    1. 其它两种基本的SQL99表达式(IF模型/SWITCH模型)都支持,但是不支持Oracle独有的decode函数

     

    3. 正则查询

     

    4. 公用表达式(CTE)

     

     

    第三节 内置函数

    1. 数值函数和字符串函数

     

     

    2. 日期时间函数

     

    3. 类型转换函数

    注意:

    1. Mysql字符串转数值转换失败时不会报错,如CAST('中' AS SIGNED)'中'+1分别返回0和1,而Oracle中会报“无效数字”错误。

     

    4. 窗口函数

    1) 窗口函数简介

    窗口函数可以对数据进行分组,不同的是,分组操作会把分组的结果聚合成一条记录,而窗口函数是将结果置于每一条数据记录中

    image-20231202112918463

    窗口函数的语法结构是:

    注意:

    1. MySQL从8.0版本开始支持窗口函数,文档地址为Window Function Descriptions

    2. 窗口函数可以分为 静态窗口函数动态窗口函数

      • 静态窗口函数的窗口大小是固定的,不会因为记录的不同而不同;

      • 动态窗口函数的窗口大小会随着记录的不同而变化。

     

    2) 求和函数

     

    3) 序号函数

     

    4) 分布函数

     

    5) 前后函数

     

    6) 首尾函数

     

    7) 其它窗口函数

     

     

    5. 其它函数

    注意:

    1. group_concat()最多拼接1024字节数据,可通过参数进行修改:

    第一节 SQL性能分析

    1. SQL执行频率

    根据SQL执行频率可以判断当前数据库是以增删改为主,还是以查询为主。

     

     

    2. 查询日志

    查询日志记录了客户端的所有操作语句,且包括二进制日志不包含的DQL语句。

    注意:

    1. 查询日志默认关闭,需要修改配置并重启服务器后才能打开。

    2. 如果长时间高频执行SQL语句,该日志文件将会非常大。

     

    3. 慢查询日志

    慢查询日志记录了执行时间超过 long_query_time 且扫描记录数不小于min_examined_row_limit 的SQL语句。

    注意:

    1. 慢查询日志默认关闭,需要修改配置并重启服务器后才能打开。

    2. 慢查询日志默认不记录管理语句和未使用索引的语句,需要修改配置打开。

     

    4. 明细耗时(profile)

    profile能够记录SQL语句各详细步骤的执行耗时。

     

     

    5. 执行计划(explain)

    explain可以获取某SQL的执行计划,包括如何提取数据、如何进行表连接、如何过滤数据等。

    执行计划中各字段的简要说明如下:

     

     

    第二节 合理使用索引

    1. 索引存储结构

    索引按存储结构可分为B+树索引哈希(Hash)索引全文(FullText)索引R-Tree(空间索引)等,不同存储引擎的支持情况如下:

    索引结构类型\引擎类型InnoDBMyISAMMemory
    B+Tree索引支持支持支持
    Hash索引  支持
    FullText索引(倒排索引)支持(Mysql5.6+)支持 
    R-tree(空间索引) 支持 

     

    1) B+Tree索引

    MySql中的B+Tree索引从二叉树=>红黑树(自平衡二叉树)=>B-Tree(非叶子节点也存储数据的多叉树)=>B+Tree(仅叶子节点存储数据的多叉树,且叶子节点使用单向链表连接)一路发展而来,解决了二叉树顺序插入退化为链表的问题,解决了红黑树大数据量下层级较深的问题,解决了B-tree非叶子节点存储数据的问题,解决了B+Tree无反向链表不方便范围查找的问题,结构图示意如下:

    image-20231115192347199

    扩展:如何预估B+Tree索引的高度?

    答:在B+Tree索引中,一个结点有一页的空间,而在InnoDB引擎中,一页的大小默认为16k,一个指针的大小为6字节,假设主键为BIGINT类型,占8个字节,则一个非叶子结点可以存储16*1024/(6+8)=1170个索引指针,那么可以算出两层最大支持1*1170页数据,三层最多支持1*1170*1170=1,368,900页数据,当一行数据为1k时,大约为1368900*16k/1k=2200万行。

     

    2) Hash索引

    哈希索引就是采用一定的hash算法,将键值换算成新的hash值,映射到对应的槽位上,然后存储在hash表中。如果两个(或多个)键值,映射到一个相同的槽位上,他们就产生了hash冲突(也称为hash碰撞),可以通过链表来解决。

    image-20231115194152326

    注意:

    1. Hash索引查询效率非常高,通常只需要一次检索就可以了(不存在hash冲突的情况),效率通常要高于B+tree索引。

    2. 但是Hash索引只能用于对等比较(=,in),不支持范围查询(between,>,< ,...),且无法利用索引完成排序操作。

     

    3) FullText索引

    全文索引是通过倒排索引来实现的,类似ElasticSearch等搜索引擎的实现,对在大文本中检索关键词的场景非常有效。

     

    4) 关于聚集索引

    在InnoDB引擎中,B+树索引根据索引块和数据块存放的位置,将其分为聚集索引二级索引

    image-20231115190030401

     

     

    2. 添加索引提示

     

     

    3. 索引设计原则

     

     

     

    第三节 特殊场景优化

    1. 主键优化

    在InnoDB存储引擎中,表数据都是根据主键顺序组织存放的,这种存储方式的表称为索引组织表(index organized table IOT)。

    image-20231116193256598

    由于一页的存储空间有限,当主键乱序插入执行删除操作时,就可能出现页分裂页合并。因此在满足业务需要的情况下,尽量使用自增主键,防止插入时出现页分裂,并降低主键长度,以便一页中能够存储更多的主键,同时,也应该尽量避免对主键进行修改。

     

    2. 插入优化

     

    3. 排序和分组优化

    排序和分组都可以使用索引,但要保证符合最左前缀法则。当使用索引进行排序时,执行计划中将显示Using index,否则将显示Using filesort,表示在排序缓冲区或文件排序。当分组未使用到索引时,执行计划中也会出现Using temporary等类似字样。

     

    4. 分页优化

    使用Limit进行分页查询时,页数越大则查询越慢,因为要对前M*N条数据进行额外的排序,可以通过两层查询或业务键限制优化。

     

    5. COUNT优化

    在InnoDB引擎中,按效率排序为:COUNT(*) ≈ COUNT(1) > COUNT(主键) > COUNT(普通字段)。

    特殊的,使用Count(*)时InnoDB引擎会在服务层直接按行进行累加。

     

    6. UPDATE优化

    在InnoDB引擎中,更新操作是对索引加锁的(Orace是对数据行加锁的),如果WHERE条件不存在索引,则会升级为表锁。

     

     

    第06章_过程操作

    第一节 存储过程

    1. 基本语法

    注意:

    1. 在命令行执行存储过程时,需通过DELIMITER //执行存储过程结束符。

    2. 在声明参数变量时,一般不加@符号

     

    2. 变量

    在MySQL中变量分为三种类型: 系统变量(全局变量+会话变量)、用户定义变量、局部变量。

     

    1) 系统变量

    系统变量是MySQL服务器层面的变量,又分为全局变量(对所有会话生效)和会话变量(仅当前会话生效),命名一般以@@开头。

    注意:

    1. 如果没有指定SESSION或GLOBAL,则默认是SESSION变量。

    2. mysql服务重新启动之后,所设置的全局参数会失效,要想不失效,可以在 /etc/my.cnf 中配置。

     

    2) 用户定义变量

    用户可以根据需要自己定义变量,用户变量不用提前声明,以@变量名格式直接使用即可,其作用域为当前连接

    注意:

    1. 用户变量赋值使用=:=都可以。

     

    3) 局部变量

    局部变量一般用作存储过程的参数列表内部变量,需要DECLARE显示声明,在其声明的BEGIN...END块内有效,一般不加@@@

    局部变量的类型和数据库字段类型基本一致,包括INT、BIGINT、CHAR、VARCHAR、DATE、TIME等。

    注意:

    1. 局部变量作为输入输出参数时,需要指明输入输出类型,可以是INOUTINOUT三种之一。

     

     

    3. 流程控制

    1) IF语句

     

    2) CASE语句

     

    3) WHILE语句

     

    4) REPEAT语句

     

    5) LOOP语句

     

    4. 游标

    游标(CURSOR)是用来存储查询结果集的数据类型 , 在存储过程和函数中可以使用游标对结果集进行循环的处理。

     

     

    第二节 存储函数

    存储函数是有返回值的存储过程,存储函数的参数只能是IN类型的。

     

    1. 语法说明

    关于characteristic说明:

    注意:

    1. 在mysql8.0中默认开启binlog,这要求在定义存储过程时指定characteristic特性,否则会报错。

     

    2. 简单示例

     

     

    第三节 触发器

    1. 触发器简介

    触发器是与表有关的数据库对象,指在insert/update/delete之前(BEFORE)或之后(AFTER),触发并执行触发器中定义的SQL语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性、 日志记录、数据校验等操作。

    使用别名OLDNEW来引用触发器中发生变化的记录内容,这与其他的数据库是相似的。

    触发器类型NEW 和 OLD
    INSERT 型触发器NEW 表示将要或者已经新增的数据
    UPDATE 型触发器OLD 表示修改之前的数据 , NEW 表示将要或已经修改后的数据
    DELETE 型触发器OLD 表示将要或者已经删除的数据

    注意:

    1. Mysql8.0版本触发器还只支持行级触发,不支持语句级触发。

     

    2. 语法说明

     

    3. 简单示例

    通过触发器记录 tb_user 表的数据变更日志,将变更日志插入到日志表user_logs中, 包含增加、修改、删除操作;

     

    第07章_扩展提高

    第一节 InnoDB引擎结构

    1. 逻辑存储结构

    InnoDB引擎的逻辑存储结构如下图所示:

    image-20231125160116758

    提示:

    1. 在Oracle逻辑结构中,表空间之下按层次分为段(数据段/索引段/回滚段/临时段)

     

     

    2. 内存存储结构

    InnoDB引擎的内存结构如下图左边部分所示,主要分为 Buffer Pool、Change Buffer、Adaptive Hash Index、Log Buffer 四大块。

    image-20231125161657087

     

    1) Buffer Pool

    缓存高频使用的数据页索引页undo页、插入缓存、自适应哈希索引、InnoDB锁信息等。在执行增删改查时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘,从而减少磁盘IO,加快处理速度。

     

    2) Change Buffer

    针对非唯一二级索引页设置的更改缓冲区,在执行DML语句时,如果这些数据页没有在 Buffer Pool 中,不会直接操作磁盘,而会将数据变更存在更改缓冲区 Change Buffer中,在未来数据被读取时,再将数据合并恢复到Buffer Pool中,再将合并后的数据刷新到磁盘中。 Change Buffer的意义是什么呢?先来看一幅图,这个是二级索引的结构图:

    image-20231125164611219

    与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。删除和更新可能会影响索引树中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了ChangeBuffer之后,我们可以在缓冲池中进行合并处理,减少磁盘IO。

     

    3) Adaptive Hash Index

    InnoDB引擎不自持Hash索引,但是会根据查询性能监控情况,自动建立自适应哈希索引,无需人工干预。

     

    4) Log Buffer

    日志缓冲区,缓存REDO日志UNDO日志,默认大小为 16MB,会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘 I/O。

     

     

    3. 磁盘存储结构

    1) System Tablespace

    系统表空间,默认文件名为ibdata1,用于存储 Change Buffer ,以及创建在系统表空间中的表和索引数据。

     

    2 ) File-Per-Table Tablespaces

    当开启innodb_file_per_table开关时,为每个表都创建单独的表空间,文件名后缀为.ibd,用于存储其数据和索引。

     

    3) General Tablespaces

    通用表空间,需要手动创建并在建表时指定其存储的表空间,和Oracle中表空间的用法类似。

     

    4) Undo Tablespaces

    撤销表空间,MySQL实例在初始化时会自动创建两个默认的undo表空间(初始大小16M),用于存储undo log日志

     

    5) Redo Log

    重做日志,在事务提交时写入(顺序写,比较快),当数据库崩溃重启时,用于数据恢复。重做日志存在多个文件,以循环的方式写入:

    image-20231125170642469

     

    6) Doublewrite Buffer Files

    双写缓冲区,innoDB引擎将数据页从Buffer Pool刷新到磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据。

    image-20231125170610953

     

    7) Temporary Tablespaces

    InnoDB 使用会话临时表空间和全局临时表空间,存储用户创建的临时表等数据。

     

    4. 后台线程组

    在InnoDB的后台线程中,分为4类,分别是:Master Thread 、IO Thread、Purge Thread、Page Cleaner Thread。

    image-20231125172429836

     

    1) Master Thread

    核心后台线程,负责调度其他线程,还负责将缓冲池中的数据异步刷新到磁盘中,保持数据的一致性,还包括脏页的刷新、合并插入缓存、undo页的回收。

     

    2) IO Thread

    在InnoDB存储引擎中大量使用了AIO来处理IO请求,这样可以极大地提高数据库的性能,而IOThread主要负责这些IO请求的回调。

    线程类型默认个数职责
    Read thread4负责读操作
    Write thread4负责写操作
    Log thread1负责将日志缓冲区刷新到磁盘
    Insert buffer thread1负责将写缓冲区内容刷新到磁盘

    我们可以通过以下的这条指令,查看到InnoDB的状态信息,其中就包含IO Thread信息。

     

    3) Purge Thread

    主要用于回收事务已经提交了的undo log,在事务提交之后,undo log可能不用了,就用它来回收。

     

    4) Page Cleaner Thread

    协助 Master Thread 刷新脏页到磁盘的线程,它可以减轻 Master Thread 的工作压力,减少阻塞。

     

     

    5. 扩展:索引存储结构

    在InnoDB引擎中,根据索引块和数据块存放的位置,将其分为聚集索引二级索引

    image-20231115190030401

     

     

     

    第二节 事务原理

    1. 事务的四大特性

    事务是一组操作的集合,这些操作要么全部成功,要么全部失败,它具有原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)四大特性。

    从实现原理来看,可以把这四大特性分为两个部分,其中原子性、一致性和持久性由 REDO LOGUNDO LOG 保证,而隔离性是通过数据库的MVCC机制来保证的。

    image-20231127202401631

     

     

    2. 重做日志与回滚日志

    重做日志记录事务提交时数据页的修改(物理日志),用来优化事务的持久化性能。如果没有重做日志,那么将采用随机写磁盘的方式,会非常慢,采用重做日志后,先顺序写重做日志,再异步刷新磁盘数据,这种方式被称为(WAL,Write-Ahead Logging,先写日志)。

    image-20231127203317537

    回滚日志记录数据被修改前的信息(逻辑日志,如DELETE语句记INSERT,UPDATE语句记相反的UPDATE等),主要用于回滚(保证事务的原子性)MVCC(多版本并发控制) ,存储在表空间中的回滚段

    扩展:关于重做日志和回滚日志的有效期

    1. 重做日志在将数据刷新到磁盘后,就可以删除了,因此采用循环写的方式。

    2. 回滚日志在事务执行时产生,但在事务提交时并不会立即删除回滚日志,可能还会被用于MVCC。

     

     

    3. 多版本并发控制(MVCC)

    多版本并发控制(MVCC,Multi-Version Concurrency Control)指维护一个数据的多个版本,使得读写操作没有冲突(快照读,读历史版本),Mysql中的具体实现是依赖记录中的隐藏字段回滚日志读视图(readView)等。

     

    1) 隐藏字段
    隐藏字段含义
    DB_TRX_ID最近修改事务ID,记录插入这条记录或最后一次修改该记录的事务ID
    DB_ROLL_PTR回滚指针,配合 undo log 使用,指向这条记录的上一个版本
    DB_ROW_ID隐藏主键,如果表结构没有指定主键,将会生成该隐藏字段

    提示:

    1. 隐藏字段可通过ibd2sdi stu.ibd命令查看。

     

    2) 回滚日志

    回滚日志指在 insert、update、delete 的时候产生的便于数据回滚的日志。当insert的时候,产生的undo log日志只在回滚时需要,在事务提交后可被立即删除。而update、delete的时候,产生的undo log日志不仅在回滚时需要,在快照读时也需要,不会立即被删除。

    例如:插入1条数据并重复修改2次,将产生如下的回滚日志(注:日志内容仅做示意,实际上回滚日志是逻辑日志)。

    image-20231127210520778

     

    3) 快照读与读视图

    快照读指读取记录的可见版本,有可能是历史数据,不加锁,是非阻塞读。

    ReadView(读视图)快照读 SQL执行时MVCC提取数据的依据,记录并维护系统当前未提交事务的id。它包含四个核心字段:

    字段含义
    m_ids当前活跃的事务ID集合
    min_trx_id最小活跃事务ID
    max_trx_id预分配事务ID,当前最大事务ID+1(因为事务ID是自增的)
    creator_trx_idReadView创建者的事务ID

    而在readview中规定了版本链数据的访问规则,如下图所示,其中 trx_id 代表当前undolog版本链对应事务ID

    条件是否可以访问说明
    trx_id == creator_trx_id可以访问该版本说明数据是当前这个事务更改的
    trx_id < min_trx_id可以访问该版本说明数据已经提交了
    trx_id > max_trx_id不可以访问该版本说明该事务是在ReadView生成后才开启
    min_trx_id <= trx_id <= max_trx_id如果trx_id不在m_ids中,是可以访问该版本的说明数据已经提交

    扩展:

    1. 当前读指读取记录的最新版本,读取时还要保证其他并发事务不能修改当前记录,会对读取的记录进行加锁。如:select ... lock in share mode(共享锁),select ...for update、update、insert、delete(排他锁)都是一种当前读。

     

     

    4. RC实现原理分析

    RC隔离级别下,在事务中每一次执行快照读时生成读视图(ReadView)。

    image-20231127212608676

    image-20231127212700078

    image-20231127212736759

    image-20231127212815600

    image-20231127212839400

    image-20231127212906410

    image-20231127212932370

     

     

    5. RR实现原理分析

    RR隔离级别下,仅在事务中第一次执行快照读时生成ReadView,后续复用该ReadView。 而RR 是可重复读,在一个事务中,执行两次相同的select语句,查询到的结果是一样的

    image-20231127213015039

    image-20231127213104966

     

     

    第三节 主从复制

    1. 主从复制简介

    主从复制是指将主数据库的 DDL 和 DML 操作通过二进制日志传到从库服务器中,然后在从库上对这些日志重新执行(也叫重做),从而使得从库和主库的数据保持同步。

    MySQL支持一台主库同时向多台从库进行复制, 从库同时也可以作为其他从服务器的主库,实现链状复制。

    主从复制的优点主要包含以下三个方面:

     

    2. 主从复制原理

    MySQL主从复制的核心就是二进制日志,具体的过程如下:

    image-20231201181007992

    从上图来看,复制分成三步:

    1. Master 主库在事务提交时,会把数据变更记录在二进制日志文件 Binlog 中。

    2. 从库读取主库的二进制日志文件 Binlog ,写入到从库的中继日志 Relay Log

    3. slave重做中继日志中的事件,将改变反映它自己的数据。

     

    3. 主从复制配置

    1) 主库配置

     

    2) 从库配置

     

     

    第四节 分库分表

    查看相关独立文档!

     

    第五节 读写分离

    查看相关独立文档!