Mysql概览
Mysql介绍
连接池(Connection Pool):用来管理MySQL的连接,缓存连接
管理服务和组件(Management Services ): 系统管理和控制工具,比如备份恢复,MySQL同步,集群等
SQL接口(SQL Interface): 用来接受SQL命令,返回用户需要查询的结果
解析器(Parser):按照SQL语法解析SQL命令
优化器(Optimizer): 查询优化器,优化传入的SQL命令
缓存器(Caches & Buffers):缓存,用来缓存一部分热点数据,比如表缓存,记录缓存等
插件式存储引擎(Pluggable Storage Engines):真正执行查找,存储的数据引擎,不同的引擎支持的操作不同,MySQL的存储引擎是基于表的。
物理文件(File System):持久化的一些数据,包括存储的数据,Redo,Undo,Index...
InnoDB介绍
InnoDB一个支持事务安全的存储引擎,同时也是mysql的默认存储引擎。
大家都知道mysql中数据是存储在物理磁盘上的,而真正的数据处理又是在内存中执行的。由于磁盘的读写速度非常慢,如果每次操作都对磁盘进行频繁读写的话,那么性能一定非常差。为了上述问题,InnoDB将数据划分为若干页,以页作为磁盘与内存交互的基本单位,一般页的大小为16KB。这样的话,一次性至少读取1页数据到内存中或者将1页数据写入磁盘。通过减少内存与磁盘的交互次数,从而提升性能。
日志
MySQL日志
MySQL的日志可以分为错误日志、二进制文件、查询日志和满查询日志。
错误日志 很好理解,就是服务运行过程中发生的严重错误日志。当我们的数据库无法启动时,就可以来这里看看具体不能启动的原因是什么
二进制文件 它有另外一个名字你应该熟悉,叫Binlog,其记录了对数据库所有的更改。
查询日志 记录了来自客户端的所有语句
慢查询日志 这里记录了所有响应时间超过阈值的SQL语句,这个阈值我们可以自己设置,参数为long_query_time,其默认值为10s,且默认是关闭的状态,需要手动的打开。
1 Error Log :
错误日志文件,错误日志文件记录了MySQL启动,运行,关闭等记录,同时包含一些警告信息,当发现MySQL有异常的时候,应该第一时间查看错误日志文件。
SHOW VARIABLES LIKE 'log_error'
2 Slow Log
慢查询日志可以监控执行超过指定时间的SQL,从而记录到日志中,默认情况下MySQL并不启动慢查询日志,用户需要手工将这个参数设置为ON
SHOW VARIABLES LIKE 'log_slow_queries'; //查询是否开启慢查询日志
ShOW VARIABLES LIKE 'long_query_time'; //查询慢日志的阈值,默认10s
SHOW VARIABLES LIKE 'log_queries_not_using_indexes'; //记录所有没有使用索引的SQL
SHOW VARIABLES LIKE 'log_throttle_queries_not_using_indexes'; //设置没有记录索引的SQL的运行次数阈值,只有超过这个阈值才记录
SHOW VARIABLES LIKE 'log_output'; //看出日志输出格式
3 查询日志
查询日志记录了所有对MySQL数据库的所有请求信息,无论这些请求是否得到了正确的执行。
4 Binary Log
二进制日志记录了MySQL数据库执行的所有的更改操作,但是不包括SELECT和SHOW等操作。通过二进制日志,可以达到以下几种功能:
恢复:通过二进制日志恢复数据
复制:在主从同步的时候,通过二进制日志,将主数据库信息同步到从数据库中
审计:通过二进制日志,可以统计操作,查看是否存在SQL注入
InnoDB日志
1 Redo Log
Redo Log 重做日志,用于记录事务操作的变化,且记录的是修改之后的值。不管事务是否提交都会记录下来。例如在更新数据时,会先将更新的记录写到Redo Log中,再更新缓存中页中的数据。然后按照设置的更新策略,将内存中的数据刷回磁盘。
2 Undo Log
Undo Log 记录的是记录的事务开始之前的一个版本,可用于事务失败之后发生的回滚。
Redo Log记录的是具体某个数据页上的修改,只能在当前Server使用,而Binlog可以理解为可以给其他类型的存储引擎使用。这也是Binlog的一个重要作用,那就是主从复制,另外一个作用是数据恢复。
如何存储表
MySQL 使用 InnoDB 存储表时,会将表的定义和数据索引等信息分开存储,其中前者存储在 .frm 文件中,后者存储在 .ibd 文件中。
.frm 文件
无论在 MySQL 中选择了哪个存储引擎,所有的 MySQL 表都会在硬盘上创建一个 .frm 文件用来描述表的格式或者说定义;.frm 文件的格式在不同的平台上都是相同的。
CREATE TABLE test_frm( column1 CHAR(5), column2 INTEGER);
.ibd 文件
InnoDB 中用于存储数据的文件总共有两个部分,一是系统表空间文件,包括 ibdata1、 ibdata2 等文件,其中存储了 InnoDB 系统信息和用户数据库表数据和索引,是所有表公用的。
页
页,是InnoDB中数据管理的最小单位。当我们查询数据时,其是以页为单位,将磁盘中的数据加载到缓冲池中的。同理,更新数据也是以页为单位,将我们对数据的修改刷回磁盘。每页的默认大小为16k,每页中包含了若干行的数据。
用户自己的存储的数据会按照对应的行格式存在User Records中。实际上,新生成的页面是没有User Records的,只有当我们第一次插入数据时,才会从Free Space划一个记录大小的空间给User Records。当Free Space用完之后,就意味着当前的数据页也使用完了。
每一页的数据,可以通过FileHeader中的上一下和下一页的数据,页与页之间可以形成双向链表。因为在实际的物理存储上,数据并不是连续存储的。你可以把他理解成G1的Region在内存中的分布。
而一页中所包含的行数据,行与行之间则形成了单向链表。我们存入的行数据最终会到User Records中,当然最初User Records并不占据任何存储空间。随着我们存入的数据越来越多,User Records会越来越大,Free Space的空间会越来越小,直到被占用完,就会申请新的数据页。
User Records中的数据,是按照主键id来进行排序的,当我们按照主键来进行查找时,会沿着这个单向链表一直往后找
缓冲池
InnoDB为了做数据的持久化,会将数据存储到磁盘上。但是面对大量的请求时,CPU的处理速度和磁盘的IO速度之间差距太大,为了提高整体的效率, InnoDB引入了缓冲池。
当有请求来查询数据时,如果缓存池中没有,就会去磁盘中查找,将匹配到的数据放入缓存池中。同样的,如果有请求来修改数据,MySQL并不会直接去修改磁盘,而是会修改已经在缓冲池的页中的数据,然后再将数据刷回磁盘,这就是缓冲池的作用,加速读,加速写,减少与磁盘的IO交互。
缓冲池说白了就是把磁盘中的数据丢到内存,那既然是内存就会存在没有内存空间可以分配的情况。所以缓冲池采用了LRU算法,在缓冲池中没有空闲的页时,来进行页的淘汰。但是采用这种算法会带来一个问题叫做缓冲池污染。
当你在进行批量扫描甚至全表扫描时,可能会将缓冲池中的热点页全部替换出去。这样以来可能会导致MySQL的性能断崖式下降。所以InnoDB对LRU做了一些优化,规避了这个问题。
执行一次IO过程如下: 执行SQL -> 记录Redo日志 -> 持久化Redo日志 -> 更新插入缓冲
MySQL采用日志先行,在真正写数据之前,会首先记录一个日志,叫Redo Log,会定期的使用CheckPoint技术将新的Redo Log刷入磁盘,这个后面会讲。
除了数据之外,里面还存储了索引页、Undo页、插入缓冲、自适应哈希索引、InnoDB锁信息和数据字典。
缓冲池的大小直接影响数据库的整体性能,对于InnoDB存储引擎而言,缓冲池配置通过参数 innodb_buffer_pool_size 来设置。使用 SHOW VARIABLES LIKE 'innodb_buffer_pool_size'
命令可查看缓冲池配置:
mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size'
*************************** 1. row ***************************
Variable_name: innodb_buffer_pool_size
Value: 134217728
1 row in set (0.01 sec)
两次写
1 当刷新缓冲池脏页时,并不直接写到数据文件中,而是先拷贝至内存中的两次写缓冲区。
2 接着从两次写缓冲区分两次写入磁盘共享表空间中,每次写入1MB
3 待第2步完成后,再将两次写缓冲区写入数据文件
InnoDB和MyISAM的区别
事务 InnoDB支持事务、回滚、事务安全和奔溃恢复。而MyISAM不支持,但查询的速度要比InnoDB更快
主键 InnoDB规定,如果没有设置主键,就自动的生成一个6字节的主键,而MyISAM允许没有任何索引和主键的存在,索引就是行的地址
外键 InnoDB支持外键,而MyISAM不支持
表锁 InnoDB支持行锁和表锁,而MyISAM只支持表锁
全文索引 InnoDB不支持全文索引,但是可以用插件来实现相应的功能,而MyISAM是本身就支持全本索引
行数 InnoDB获取行数时,需要扫全表。而MyISAM保存了当前表的总行数,直接读取即可。
索引划分
从逻辑角度
主键索引:主键索引是一种特殊的唯一索引,不允许有空值
普通索引或者单列索引:每个索引只包含单个列,一个表可以有多个单列索引
多列索引(复合索引、联合索引):复合索引指多个字段上创建的索引,只有在查询条件中使用了创建索引时的第一个字段,索引才会被使用。使用复合索引时遵循最左前缀集合
唯一索引
全文索引
从数据结构的角度
B+树索引:最常见的索引类型,基于B+树数据结构(InnoDB和MyISAM引擎、memory引擎)
Hash索引:基于hash表,所以只支持精确查找(时间复杂度O(1)),不支持范围查找(Memory引擎)
全文索引:主要用来查找文本中的关键字(MyISAM,InnoDB)
空间索引:基于R树实现,用于地理数据存储(MyISAM)
从物理存储角度
聚簇索引:表中记录的物理顺序与键值的索引顺序相同,数据库主键就是聚簇索引
非聚簇索引:表中记录的物理顺序与键值的索引顺序不相同 Mysql中InnoDB引擎的主键索引为聚簇索引,MyISAM存储引擎采用非聚簇索引
