MySQL内核整理(一)
一、在共享表空间(系统表空间)中,innodb会维护一些系统信息:
1、Internal data dictionary
2、Rollback segments
3、undo space
4、insert buffer
5、Double write buffer
6、MySQL replication info
二、Innodb索引结构:
1、所有的Innodb索引都是B+树结构,索引记录放在叶子节点.
2、data page页默认16kb,当有新索引记录写入时,会预留1/16(1kb)空闲空间用于以后的索引记录写入
3、当索引记录按照顺序(正序、倒叙)写入时,最理想的结果是索引页能填充15/16;如果随机无序写入,则索引页填充率可能会从1/2-15/16,当fill factor(填充因子)小于1/2时,会开始收缩数据页,释放空闲空间
4、5.6开始修改page size,支持4k、8k、16k、初始化时指定,后续无法修改,不同page size的实例间也不能直接迁移使用.5.7开始扩展到32kb、64kb。
5、innodb表为IOT,采用了B+树类型,故每个页面至少存储2行数据,如果行过大则会产生溢出;
6、理论上Innodb表中varchar(65535)的字节,但对于Innodb其实上限为65532,且该值为表所有varchar列长度总和;对于utf-8字符集,一个字符集占3个字节,则其上限又缩小为1/3;如果强制创建varchar(65535)的字段,在SQL_mode部位restricted的情况下,其会被隐式转换为mediumtext;不论是varchar还是blob/text,只要保证一个16k的页面能容下2行数据,应该不会溢出;而一旦行溢出,字段前768字节(Antelope格式)依旧存放于当前页面,数据一般使用B-tree Node页,而溢出的行存放于Uncompress Blob页;而barracuda采用了完全行溢出,即只保留字段的前20字节.
7、当file format为Antelope时,支持:REDUNDANT、COMPACT这两种行格式.发生行溢出时,在当前page会存储前768字节,多余的放在off-page.
8、当file format为Barracuda时,支持:compress,dynamic这两种格式,并兼容前两种,在当前page会存储前20字节,多余的放在off-page.
9、在多版本方式下,当你使用SQL语句删除某一行的时候,该行并不会马上从数据的物理文件上移除.只有当Innodb能够删除掉更新日志记录的时候,那些行及其对应的索引记录才会真正从物理上删除掉.这个移除操作称为purge
option:
innodb_file_format_max = barracuda
innodb_file_format = barracuda
要设置成一样,并且同时最好把innodb_file_format_check设置为1(默认值也是1),避免Innodb在启动过程中需要恢复数据,因为没有检查而写入不支持格式的表中,导致数据丢失.
当file format 为Antelope时,支持REDUNDANT、COMPACT这两种行格式
当file format为Barracuda时,支持:COMPRESS、DYNAMIC这两种行格式,并且兼容前两种
【重点】关于Innodb行格式的选择
1、compact格式消耗磁盘空间和备份耗时最下,redundant相比之下略大一些.建议采用默认compact格式,适用于绝大数场景;
2、dynamic及compressed格式下.大字段数据存储在off-page中,如果不需要读取大字段效率较高,否则效率很差.因此count(*)之类的操作相对快,但进行备份需要全表扫描时,其代价反而更高;适用于很多大字段但无需经常被更新且备份的表.
三、消除碎片
1、随机方式插入新数据,可能导致辅助索引产生大量的碎片,意思是索引page和索引顺序不接近,或者有大量的空洞. 执行alter table xxx engine = Innodb;可以重新创建表空间,消除碎片、或者备份数据表,删掉,重新导入
四、回收表空间
1、共享表空间无法在线回收,共享表空间想要回收的话,需要全部Innodb导出、删除、导入,数据表空间用上面方法即可,或者直接清空不需要保存的历史表,临时表 truncate table
五、Checkpoint
1、innodb会批量的把buffer pool中的脏页以及redo log 刷新到磁盘,称之为检查点.
2、并不是在一次刷新中刷新所有的内容,因为这样会降低mysql的性能,甚至无法提供服务
3、在恢复的过程中,innodb会向前扫描实务日志,把这些脏数据刷新到磁盘中
4、innodb循环使用它的事务日志,所以旧的日志必然在未来某一时刻被覆盖,innodb必须保证,在旧日志被覆盖之前,与这些旧日志条目相关的脏数据都被刷新到了磁盘
5、如果这一点不能保证,万一服务器crash,buffer pool中的脏页就永远也无法恢复了.
6、所以在切换日志的时候,innodb必然会做检查点,把所有的脏页都刷新到磁盘
7、从这个意义上,innodb的事物日志越大,节省的磁盘IO越多,对系统性能越好.但是crash后恢复的时间肯定会变长
8、innodb的检查点每隔几秒钟就会做一次
9、只是经过日志切换后,在日志被冲用前,该日志的内容必须被全部刷新到磁盘,否则系统就会hung住
10、尝试用大一点的事务日志,可以减少检查点过程中写磁盘的次数(之所以节省,是因为IO的合并)
Checkpoint触发条件
1、每1秒,若buffer pool中的脏页比率超过了srv_max_buf_pool_modified_pct = 75,则进行checkpoint,刷脏页, flush PCT_IO(100)的dirty pages = 200(参数:innodb_io_capacity 能够对其定义);若采用adaptive flushing,则计算flush rate,进行必要的flush。
2、每10秒,若buffer pool中的脏页比率超过了70%,flush PCT_IO(100)的dirty pages,若buffer pool中的脏页比率未超过70%,flush PCT_IO(10%)的dirty pages = 20;每10s,必定调用一次log_checkpoint,做一次checkpoint
脏页比率 = 需要被flush的页面数/(使用中的页面数+空闲页面数+1)
innodb_adaptive_flushing_lwm —设置redo log flush低水位线,当需要flush的redo log超过这个低水位时,立即强制启用adaptive flushing,即便没有设置使用adaptive flush 机制
innodb_io_capacity = N —-设置Innodb后台进程最大的IO性能指标,列如:从buffer pool中刷新数据页,从insert buffer中合并数据等.默认值200,在繁忙的OLTP模式下,需要适当提高.
innodb_io_capacity_max = N —设置Innodb_io_capacity_在紧急情况下的上限值
innodb_flushing_avg_loops = N —-设置Innodb统计前N个page flush 速率,避免太快flush
【问题】Innodb都有哪些后台进程?
后台线程(15个)
1、master thread(1个)
2、lock monitor thread(1个)
3、error monitor thread(1个)
4、log thread(1个)
5、read/write thread(8个,默认各4个)
6、purge thread(1个)
7、page cleaner thread(1个)
如下source code:
master_thread_main_loop()
loop:
{
//A、每秒需要执行的
for(int i=;i<;i++) //sleep 1s
//每秒都要刷新日志缓存到磁盘
{
do log buffer flush to disk;
}
//如果缓存中的脏页比例大于配置中的innodb_max_dirty_pages_pct就刷新innodb_io_capacity个脏页到硬盘
if(last_one_second_iosinnodb_max_dirty_pages_pct)
{
do buffer pool flush % innodb_io_capacity dirty page;
}
//如果没有活跃用户或者数据关闭时,就跳入background loop
if (no user activity){
goto background loop;
}
//有必要的话,就空闲1秒
sleep second if necessary;
} //B、每10秒需要执行的
//如果最后10s内IO小于innodb_io_capacity次,那么就刷新innodb_io_capacity个脏页到磁盘
if(last_ten_second_ios < innodb_io_capacity)
{
do buffer pool flush % * innodb_io_capacity dirty page;
//总是合并最多5个插入
do merge at most insert buffer //总是将日志缓存刷新到磁盘
do log buffer flush to disk; //总是删除buffer_pool中无用的undo页,一次最多20个
do full purge;
} if (buf_get_modified_ratio_pct&get;%)
//如果缓存中脏页比例大于70%,就刷新innodb_io_capacity个脏页到磁盘,否则值只刷新10% * innodb_io_capacity个
{
do buffer pool flush % * innodb_io_capacity dirty page;
}
else
{
buffer pool flush % * innodb_io_capacity dirty page;
//产生一个检查点
do checkpoint
//返回主循环
goto loop;
} //backupgroud 循环
backupgroud loop;
{
//总是删除buffer pool中无用的undo页
do full purge //总是合并innodb_io_capacity个插入缓存
do merge % * innodb_io_capacity insert buffer //如果不空闲,就调回主循环,如果空闲就跳入flush loop
if not idle
{
goto loop:
}
else
{
goto flush loop;
flush loop;
//总是刷新innodb_io_capacity个脏页到硬盘,知道缓存中的脏页比例小于innodb_max_diry_pages_pct
do buffer pool flush % * innodb_io_capacity dirty page if(buf_get_modified_ratio_pct&get;innodb_max_dirty_pages_pct)
{
goto flush loop;
}
//完成刷新脏页的任务后,跳入suspend loop
goto suspend loop; suspend loop:
//将master线程挂起,等待事件激活
{
suspend_thread()
waiting event
}
}
}
master thread的线程优先级别最高.
其内部几个循环(loop)组成:主循环(loop),后台循环(background loop),刷新循环(flush loop),暂停循环(suspend loop)。
srv_master_thread loops: 8565077 srv_active, 0 srv_shutdown, 1939115 srv_idle
srv_master_thread log flush and writes: 10504192
master thread会根据数据运行的状态在loop,background loop,flush loop和suspend loop中进行切换,loop称为主循环,因为大多数的操作都是在这个循环中,其中有两个部分的操作:每秒的操作和每10秒的操作,loop循环通过thread sleep来实现,这意味着所谓的每一秒一次或者每10秒一次的操作是不精确的.当然,innodb源码中还采用了其他的方法来尽量保证这个频率.
@每秒一次操作包括:
1、日志缓冲(log buffer)刷新到磁盘,即使这个事务还没有提交(总是)
2、合并插入缓冲(insert buffer)可能
3、之多刷新100个innodb的缓冲池(buffer pool)中的脏页(dirty page)到磁盘(可能)
4、如果当前没有用户活动,切刀background loop(可能)
@每10秒操作包括:
1、刷新100个脏页到磁盘(可能)
2、合并之多5个插入缓冲(总是)
3、将日志缓冲刷新到磁盘(总是)
4、删除无用undo页(总是)
5、刷新100个或者10个脏页到磁盘(总是)
6、产生一个检查点(总是)
【重点】关键点:
1、dirty pages不要堆积太多,否则热点数据不能被有效缓存,命中率低,并且瞬间大批量刷新dirty pages时也影响IOPS;
2、undo pages不要堆积太多,否则ibdata1可能暴涨,或者tsp受到影响;
3、checkpoint不要延迟太厉害,否则crash recovery进程很慢;
4、记住最重要的一点,这些后踢进程有条不紊按照固定频率工作着,不要有停滞,也不要太频繁.
MySQL内核整理(一)的更多相关文章
- MySQL内核:InnoDB存储引擎 卷1
MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...
- MySQL内核深度优化
版权声明:本文由简怀兵原创文章,转载请注明出处: 文章原文链接:https://www.qcloud.com/community/article/179 来源:腾云阁 https://www.qclo ...
- 腾讯云数据库团队:浅谈如何对MySQL内核进行深度优化
作者介绍:简怀兵,腾讯云数据库团队高级工程师,负责腾讯云CDB内核及基础设施建设:先后供职于Thomson Reuters和YY等公司,PTimeDB作者,曾获一项发明专利:从事MySQL内核开发工作 ...
- MySQL基础整理(一)之SQL基础(未完成)
大家好,我是浅墨竹染,以下是MySQL基础整理(一)之SQL基础 1.SQL简介 SQL(Structure Query Language)是一种结构化查询语言,是使用关系模型的数据库应用语言. 2. ...
- 举个栗子看如何做MySQL 内核深度优化
本文由云+社区发表 作者介绍:简怀兵,腾讯云数据库高级工程师,负责腾讯云CDB内核及基础设施建设:先后供职于Thomson Reuters和YY等公司,PTimeDB作者,曾获一项发明专利:从事MyS ...
- MySQL 安全整理
MySQL 安全整理 关闭外网的端口访问. 使用高位的端口号. 如果需要外网访问不给最高的权限. 如果需要外网访问也是绑定客户端. To be continued
- PHP调用mysql函数整理
mysql函数整理 名称:mysql_connect() 用途:打开非持久的 MySQL 连接.如果成功,则返回一个 MySQL 连接标识,失败则返回 FALSE. 语法:mysql_connect( ...
- 如何深度优化MySQL内核
MYSQL数据库适用场景广泛,相较于Oracle.DB2性价比更高,Web网站.日志系统.数据仓库等场景都有MYSQL用武之地,但是也存在对于事务性支持不太好(MySQL 5.5版本开始默认引擎才是I ...
- MySQL 语句整理 2019-5-3
MySQL 语句整理 在整理完Oracle的一些常见用语句后,由于MySQL的语法跟Oracle略有不同,随跟PN的MySQL视频进行了间接整理. 查询薪水大于1800, 并且部门编号为20或30的员 ...
随机推荐
- sql的主键,int类型,自增,自动编号到了规定最大数,接下来数据库会怎么做
答案:它会从1开始重新编号,但是避开已经重复的值.
- WCF - Autofac IOC
/// <summary> /// IOC实例提供者,基于AutoFac /// /// </summary> public class IocInstanceProvider ...
- UVA10212 【The Last Non-zero Digit.】
暴力可做!!!(十秒还不打暴力!!!)暴力算阶乘边算边取余上代码 #include<iostream> #define int long long //开long long using n ...
- python图片处理和matlab图片处理的区别
作者:波布兰链接:https://www.zhihu.com/question/28218420/answer/39904627来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明 ...
- shell 中>/dev/null 2>&1含义
shell中可能经常能看到:>/dev/null 2>&1 命令的结果可以通过%>的形式来定义输出 分解这个组合:“>/dev/null 2>&1” 为五 ...
- SQL Server日期计算
通常,你需要获得当前日期和计算一些其他的日期,例如,你的程序可能需要判断一个月的第一天或者最后一天.你们大部分人大概都知道怎样把日期进行分割(年.月.日等),然后仅仅用分割出来的年.月.日等放在几个函 ...
- Mac OS 下安装mysqlclient报“mysql_config not found”的解决
如问题所示,应该是你没有将mysql_config所在文件夹加入系统的PATH路径,解决方案下: 1.第一步找到你的mysql_config所在位置 1.1. 如果是直接安装mysql,所在位置应该是 ...
- codeforces 354 D. Transferring Pyramid
D. Transferring Pyramid time limit per test 3 seconds memory limit per test 256 megabytes input stan ...
- LoadRunner中的IP欺骗的设置以及误区
LoadRunner中的IP欺骗的设置以及误区 最近在忙着部署web性能测试的环境后,对IP欺骗进行设置,特地做个笔记,给自己的学习历程留下点足迹. 一. 什么是IP欺骗? 做什么事首先要问个为什么, ...
- thinkphp5.0与thinkphp3.2之间的区别
5.0版本和之前版本的差异较大,本篇对熟悉3.2版本的用户给出了一些5.0的主要区别. URL和路由 5.0的URL访问不再支持普通URL模式,路由也不支持正则路由定义,而是全部改为规则路由配合变量规 ...