mysql innodb存储引擎学习(1)

mysql & innodb存储引擎

一、mysql体系结构
    mysql从体系上可以分为三个层次,连接层、sql层、存储引擎层。
1.1 连接层
    通过socket等方式接受客户端的连接,数据I/O,线程处理,处理通信协议,密码验证等功能。
1.2 sql层
    包含权限判断、查询缓存、解析器、预处理、查询优化器、缓存和执行计划。在一条sql语句在服务端被反序列出来后都需要经过这样链式的处理:对查询语句进行解析、优化改写最后生成执行计划。最后通过调用存储引擎的API接口访问数据。
1.3 存储引擎层
    mysql最核心的存储引擎为innodb。它支持事物、行锁、mvcc多版本并发控制适用于OLTP业务系统。
    innodb由三个部分组成 1 内存结构 2 线程 3 磁盘文件
    磁盘文件保存了数据库相关的所有数据,而线程负责对这些数据进行读写。内存结构保存了innodb运行需要的数据结构,缓存磁盘数据信息和提供日志缓冲。
    
二、innodb体系架构
2.1 内存结构
    mysql内存的组成分为SGA系统全局区域和PGA程序缓存区。主要看SGA:
    1. 缓冲池是一块内存区域,通过内存的速度来弥补磁盘速度较慢对数据库性能的影响。该区域主要用来缓存innodb表的数据、索引、插入缓冲、锁信息和数据字典信息。innodb允许有多个缓冲池实例,每个页根据哈希值平均分配到不同缓冲池实例中,以减少数据库内部资源竞争,增加并发性能。
    2. 重做日志缓冲是事务在内存中的缓冲,事务操作会先写日志到重做日志缓冲中,再由主线程将日志数据刷到磁盘中。
    3. 高速查询缓存。由于查询缓冲数据变化率高,建议在生产中关闭。
2.1.1 缓冲池的组织结构
    缓冲池中的数据按照段、区、页的结构进行组织。段分为数据段、索引段、回滚段等信息。一个段由N个区加32个页组成,一个区由64个连续的页组成,大小为1MB,每个页的大小为16K,页是mysql数据组织的最小单位。
每个页在内存中为分配的一个buffer。按照buffer的状态可以分为 free buffer、clean buffer、dirty buffer。通过字面意思可理解为从未使用过的buffer,内存buffer与磁盘数据页一致的buffer,内存中数据未刷到磁盘的buffer。
这些buffer在内存中是被LRU双向链表组织起来的。根据buffer的状态可分为三个LRU链表:free list、lru list、flush list。这些list将频繁使用的页放在链表前端,当内存不足时会释放链表尾端的页。当新的页被读入内存时,会将buffer插入到链表的mid位置,该位置可由参数控制。这样做主要为了保证热点数据不被刷回磁盘
free list:将那些free状态的buffer都串联起来,每次把page调到内存中时,会从free list获取buffer,如果不够用了再从lru list和flush list释放buffer
lru list: 将与磁盘数据保持一致的页加入到此链表中。每次从free list获取到页后会加入到lru list中来,当页不够时在从list末尾淘汰页内存。
flush list: 将dirty buffer串联起来,为了方便刷新线程将脏数据刷回磁盘。那些经常被修改的脏页会暂时不加入到该链表中以提高i/o效率。
2.1.2 重做日志缓冲
    innodb存储引擎首先将重做日志信息放入到这个缓冲区,然后按照一定的频率将其刷新到重做日志文件。默认情况下至少有2个redo log文件,两个文件相互覆盖,在切换文件时候会触发检查点技术,将脏页刷回磁盘。
2.1.3 检查点技术
    检查点技术就是在某些特定条件下会触发对页的检查和标记,对于标记的脏页需要将其同步回磁盘。检查点技术触发将页刷新会磁盘的操作,所以该技术主要评估什么条件下应该触发刷新脏页的操作。检查点技术主要解决三个问题,缩短数据库恢复时间;缓冲池不够用时,将脏页刷新到磁盘,重做日志不可用时刷新脏页。
sharp checkpoint
    在数据库关闭时将所有脏页刷回磁盘
fuzzy checkpoint
    只刷新一部分脏页,触发条件有 主线程检查:主线程每秒和每十秒都会刷一定数量的脏页
    flush lru list检查:lru列表需要确保有100个空闲也,所以当页面不足需要释放空闲页的时候,如果释放页是脏页需要触发刷新操作,这个过程会阻塞用户线程。
    Async/Sync Flush检查:在重做日志不可用的情况,需要强制将一些脏页刷回磁盘。innodb使用water maker标记需要触发刷脏页的条件。
    dirty page too much检查:在缓冲池中脏页比例到达一定阈值时刷新一部分脏页到磁盘。
    
2.2 线程工作
    innodb的后台线程主要分为 1个master thread负责将缓冲区数据同步到磁盘。 IO Thread,主要有4个read thread 4个wirte thread,1个insert buffer thread,1个log IO thread。1个清除undolog的purge thread,1个刷脏页的page cleaner thread
2.2.1 master thread
    主后台线程主要分为每秒任务,每10秒任务和4循环。主Loop, 后台loop,刷新loop,挂起loop. 其中每秒任务和每十秒任务在主Loop中完成。
    每秒任务:1.日志缓冲刷新到磁盘(即使这个事务还未提交、总是执行) 2.合并插入缓冲(前1秒io小于5次) 3. 至多刷新100个脏页到磁盘(脏页数量超过比例) 4. 没有用户活动切换的后台loop
    每10秒任务:1. 日志缓冲刷新到磁盘 2. 合并最多5个插入缓冲 3. 删除无用的undo页 4 刷100个或10个脏页 5 刷100个脏页(前10秒IO小于200次)
    后台loop: 1.合并插入缓冲 2. 删除无用的undo页 3 刷脏页(可能调到flush loop中) 4 调回到主循环。
    flush loop: 1 刷脏页 2. 无活动则切换到挂起loop。
2.2.2 IO thread
    innodb中大量使用了aio处理I/O请求,而IO Thread 主要用来处理这些IO请求的回调。
2.2.3 purge thread
    1.1 版本后才有,用于减小master thread的压力
2.2.4 page cleaner thread
    1.2.x 版本后才有,将刷脏页任务单独出来,用于减小master。
    
2.3 关键特性
    插入缓冲、双写、自适应哈希索引,异步IO、刷邻接页。这些特性主要为innodb存储引擎带来更好的性能和更高的可靠性。
2.3.1 插入缓冲
    如果索引不是按照顺序插入的,那么插入索引操作可能出现频繁从磁盘调页的操作。而辅助索引一般都不是按照顺序插入的,为了提高IO效率,先将辅助索引记录放入到insert buffer中。在触发检查点时才merge到索引页中,以提高效率。
    insert buffer是一个b+树的组织结构放在共享表空间中。b+树的每个叶子节点对应一张表的一个索引,如果插入一条索引记录,该记录对应的页不在内存中,则构造一个search key将其插入到insert buufer b+树的叶子节点中。构造的记录中记录了进入b+树的顺序。
    space记录了表id,offset记录了页偏移量。metadata记录进入的顺序。 insert bitmap追踪所有的索引页。
    当发生以下三个条件时触发merge操作
    1. 辅助索引页被读取到缓冲池
    2. insert bitmap追踪到无可用的索引页
    3. master thread刷新
2.3.2 双写
    为了防止数据库宕机导致页的部分写失效,采用双写机制。innodb分配了2MB的的double writer buffer在数据刷新到磁盘时,将数据复制到双写缓冲区,由双写缓冲区顺序写入到共享表空间文件,再由双写缓冲区离散的写入磁盘文件中
    由于写共享表空间是顺序写入磁盘,所以占用的开销不是很大,但是保证了可靠性。
2.3.3 自适应哈希索引 
    innodb存储引擎自动监控表上的索引页,对于热点查询建立哈希索引。哈希索引只需一次查询即可定位,而B+树所以需要树高次查询。
    触发条件有:1 以某查询模式访问了100次 2 改页通过该模式访问了 页中记录/16次。
2.3.4 异步IO 
    Native AIO需要操作系统提供支持
2.3.5 刷邻接页 
    当刷新一个脏页时,innodb会检查该页所在的区的所有页,如果是脏页则一起刷新。对于传统机械硬盘该模式具有一定优势。对于固态硬盘可以不启用。
    
2.4 启动与关闭
    mysql关闭的时候具有几种关闭行为
    0. 完成full purge 和merge insert buffer,并将脏页刷回磁盘。 这种关闭最慢,但是最安全,启动最快。
    1. 不完成full purge 和merge insert buffer,只将脏页刷回磁盘。数据库默认这种方式
    2. 只讲日志都写入日志文件。 这种启动时需要一定时间进行恢复操作。
    mysql启动时候可以设置启动行为,是否需要进行恢复等行为。一般生产环境默认需要进行恢复。
    
二、数据库文件
    数据库文件主要分为mysql产生的文件和存储引擎产生的文件。 mysql文件主要有:参数文件、错误日志、binlog、慢查询日志、查询日志。innodb存储引擎文件主要有:表空间文件、重做日志文件
2.1 参数文件
    参数文件主要描述数据库启动的参数配置,如果没有参数文件mysql将以编译时默认参数启动。参数类型分为静态和动态,动态参数在mysql实例运行时候可调,分为全局和会话调整。
2.2 错误日志 
    错误日志是mysql server在运行过程中输出的错误信息。在启动、运行河关闭的执行过程中出错,都可以通过错误日志定位原因。错误日志输出的警告信息可以帮助优化调整数据库动态参数。
2.3 慢查询日志 
    慢查询日志记录了查询语句时间超过一定阈值的记录和未走索引的记录。
2.4 查询日志 
    该日志记录了全量的客户端请求操作日志。不管请求是否得到正确执行。
2.5 二进制日志
    binlog记录数据库的更改操作,常用于主从同步和基于时间点和位置的恢复操作。开启binlog会有1%性能的下降,但是可以被接受
    记录binlog的时候会先将日志写入binlog缓冲区,在事务提交前将日志刷新到磁盘中。缓冲区是与事务线程绑定的,缓冲区的大小不宜设置过大和过下,过小则缓冲区不足时将产生一个临时文件,过大则消耗太多内存。
    在同步磁盘时,可通过参数sync_binlog进行控制。为0表示同步刷磁盘,不经过缓冲,但是带来性能的影响。为1表示每个事务提交前刷磁盘。但是如果此时宕机事务发生回顾,binlog就产生了脏数据。
    binlog_format控制了记录binlog的日志格式,statement为SQL记录,ROW为行更改记录。生产环境建议为ROW,但是增加了文件大小和网络开销。 statement开销小,但是对于具有随机函数的语句数据会不一致。
2.6 套接字文件
    unix系统下的本地连接可以采用unix域的套接字方式。这需要一个mysql.sock文件
2.7 表结构定义文件
    mysql具有一个.frm为后缀的文件,该文件记录了该表的表结构定义。

2.8 表空间文件
    ibdata 1文件是innodb的共享表空间文件。innodb将存储的数据按表空间进行存放,可以通过参数设定多个物理文件共同组成一个表空间。
    独立表空间文件会对每个表生成一个.ibd的文件用于存储该表的数据、索引等数据和插入缓冲bitmap等数据,其余数据仍放在共享表空间中。
2.9 重做日志文件 
    默认情况下innodb会产生2个ib_log_file0和ib_log_file1的文件用于记录事务日志,这两个文件循环覆盖,用户在启动时候恢复数据到关闭前状态。
    重做日志文件不宜设置过大和过小,过大则恢复时间长,过下则频繁触发检查点导致抖动。
    由于重做日志缓冲写磁盘时,按照512字节即一个扇区的大小进行写入,由于扇区是最小单位,因此保证写入必定成功。
    innodb_flush_log_at_trx_commit参数控制事务提交时是否将日志缓冲数据刷到磁盘。0 等待主线程刷 1 提交事务同步磁盘 2 重做日志异步刷到磁盘。
2.10 undo log 
    为了支持mvcc多版本并发控制,需要undo log和回滚段的支持。innodb有一个全局的事务链表,在事务开始时会将事务ID放入链表中,并通过指针指向undo 记录。
    undo 日志记录了变更前的旧数据存放在共享表空间中,mysql5.6开始使用独立的undo表空间。    

 

接下: https://blog.csdn.net/qq_32250495/article/details/102093401

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值