mysql
2021-03-04 14:51:15 5 举报
登录查看完整内容
读写流程
作者其他创作
大纲/内容
id=98
redo log 文件中和redologpoll一样是多个redologblock
默认大小为128mb有一个或多个chunk块组成可在运行期间调整chunk的大小设置参数:innodb_buffer_poll_size=8589934592(约8G)innodb_buffer_poll_instances=4(将8g内存分为4gebufferpol)mysql内存只有1g时,最多只有1个bufferpoll高的并发且硬件配置足够buffpoll的总大小 = 一个mysql服务器总内存大小的50%-60%(chunk(默认128mb)*buffpoll数量 * 2)=buffpoll总大小
主键(列长度,列支)
old roll_pointer
数据行
name=某个值
name=g
磁盘数据
指针
\tdelete mark前记录
free
id=4
被索引的各列的位置/占用空间/值
执行sql更新数据
槽位
64个连续数据页
最小id=51
id=2
IO成本就是:数据页数量 * 1.0 + 微调值,CPU成本就是:行记录数 * 0.2 + 微调值,他们俩相加,就是一个总的成本值,比如你有数据页100个,记录数有2万条,此时总成本值大致就是100 + 4000 = 4100,在这个左右。
第一个日志分组偏移量 2字节
内容
定时刷新
索引页号=29
undo type
3最大行数据类型=3
名称
更新主键
数据描述x
id=99
0普通数据行数据类型=0
1索引数据行数据类型=1
已写入数据长度(data length)2字节
同一层级指针关联
heard 12字节4各部分
0
参数innoDB_io_capacity调整到硬盘的IOPS速率,可以控制fiush缓存页随机刷盘的每秒执行次数innodb_flush_neighbors:如果是ssd盘可以将这个参数设置为0,也就是禁止刷入临近的缓存页,这样可以降低每次刷新的缓存页数量
1
主键
\t被更新列的数量
name索引的根页
2起始行数据类型=2
undo log
最小主键=98
查询顺序
3更新内存数据
被更新列更新前信息
一行数据
文件头(38字节)
\t找到修改之前最近的undo日志,比如新增的日志
当buffer poll满时这个数据区的在最后一个被刷盘,并清理
多个数据行
最小主键=1
......
全表扫描时,数据额会加载到bufferpool中,根据数据页的双向链表一页一页的做二分查找,每页都还要循环查找数据行
索引页号=20
innodb_flush_log_at_trx_commit = 0的情况下只存redologpoll中不刷盘可以通过innodb_log_buffer_size 参数指定大小默认是16mb默认为1redo log本质是保证事务提交之后,修改的数据绝对不会丢失的。如果事务中的增删改SQL语句更新的缓存页还没刷到磁盘上去,此时MySQL宕机了,那么MySQL重启过后,就可以把redo log重做一遍,恢复出来事务当时更新的缓存页,然后再把缓存页刷到磁盘就可以了包含表空间号、数据页号、磁盘文件偏移量、更新值的字节数、具体的值
最小id=1
第二个数据区
NFS文件系统
name=h
最小主键=4
最大记录最小记录共26字节
trailer(4字节)
数据页号=1
索引页页号1
TRX_UNDO_DEL_MARK_REC
name=c
主键B+TREE
IBUF_BITMAP数据页,里面存放的是这一组数据页的所有insert buffer的一些信息。
next指针指向
lru
每个bufferpoll的chunk共享这3个链表
bin log
redo log poll
name=f
第256个数据区
每个数据页16KB
索引页页号40
innoDB执行引擎
SQL语句执行组件
4写入redolog
冷热数据链当crud操作时数据从磁盘加载到buffer poll后放入冷数据区,在1s后数据再次被访问的情况下,改数据会被加载遍移动到热数据区
工作线程不停的写入
id=50
undo type\t
...
数据行单项链表,从小到大排列
........
数据描述1
id=100
2将旧数据刷入undolog
页目录
.....
数据页头(56字节)
name=a
磁盘IO
数据页
varcher(10)hellojava
数据描述3
id=某个值
null字段链表允许为null的字段,不足8位高位补0
数据页号=2
oscache
flush
索引页号=30
加载数据到缓存
描述和数据页一一对应
undolog日志类型insert:TRX_UNDO_INSERT_RECdelete:TRX_UNDO_DEL_MARK_RECupdate:TRX_UNDO_DEL_MARK_REC
pre指针指向
内存的缓存里查找数据在不在里面,如果有就基于内存缓存来执行读写,如果没有就继续往下一层走
undolog日志编号每个事务的日志编号从0开始
每个数据页都有一个页目录
联合索引的B+TREE与name索引的B+TREE差不多,区别在于单字段的索引排序只要按照这个字段的大小,小-》大,而联合索引是按照建立索引时的字段设置顺序作为优先级排序
Page Cache
部分数据
数据库还会有一个哈希表数据结构,他会用表空间号+数据页号,作为一个key,然后缓存页的地址作为value。在执行crud时先看看这个数据页有没有被缓存如果没被缓存就从free链表中找到一个空闲的缓存页,从磁盘上读取数据页写入缓存页,写入描述数据,从free链表中移除这个描述数据块,如果数据页已经被缓存了就从这个hash表数据结构中直接获取使用
varcher(10)fuck
缓存数据页3
刷入undolog
intnull
刷盘时机
数据库的每一次更新SQL语句,都必然涉及到多个磁盘随机读取数据页的操作,也会涉及到一条redo log日志文件顺序写的操作。所以磁盘读写的IOPS指标,就是每秒可以执行多少个随机读写操作,以及每秒可以读写磁盘的数据量的吞吐量指标,就是每秒可以写入多少redo log日志,整体决定了数据库的并发能力和性能。 包括磁盘日志文件的顺序读写的响应延迟,也决定了数据库的性能,因为你写redo log日志文件越快,那么你的SQL语句性能就越高。
先根据name字段值在name字段的索引B+tree里找
索引各列信息占用空间包括主键索引
TRX_UNDO_INSERT_REC
数据描述
不更新主键被更新各列占用存储空间都不变:直接在原纪录基础上改 .......变:用户线程同步地先从聚簇索引中真实的删除旧记录,不是delete mark,并修改一系列信息,再插入新记录
数据描述2
Block设备驱动层通过驱动吧IO请求发送给Block设备层
信息头
redo log poll中也有多个redologblockxt
顺序写,末尾添加磁盘每秒的吞吐量是核心关注点
索引页页号30
数据页里面大概长这样
一组(256个) extent数据区每个数据区1mb
old trix_id
n_updated
数据页1
塞满一个redologblock顺序写入
缓存页
..........
数据也
id=3
FSP_HDR这个数据页,他里面就存放了表空间和这一组数据区的一些属性
name=d
刷入磁盘
主键不是自增的,他可能会有一个数据行的挪动过程,保证你下一个数据页的主键值都大于上一个数据页的主键值。并且在数据页中的数据行也会根据主键的大小来排序挪移
name=i
这里关联主键索引进行回表查询
id=6
如果写入redo log buffer的日志已经占据了redo log buffer总容量的一半了,也就是超过了8MB的redo log在缓冲里了,此时就会把他们刷入到磁盘文件里去. 一个事务提交时,必须把redo log所在的redu log block刷入磁盘. 后台线程定时刷新,在有一个后台线程每个1秒吧redologbuffer里的redologblock刷到磁盘中去 Mysql关闭的时候,redologblock都会刷到磁盘里去
数据页2
变长字段列表例:varhcar(10)16进制存储
TRX_UNDO_DEL_MARK_REC将旧记录delete mark,因为其他事务可能需要访问(事务隔离机制)
指向数据页
id=1
执行器
Block设备层完成后,无论读还是写,都要把IO读写的结果逐层返回
通用Block层件的IO请求转换为Block IO请求交给IO调度层
建议MySQL的生产环境,需要调整为deadline IO调度算法,他的核心思想就是,任何一个IO操作都不能一直不停的等待,在指定时间范围内,都必须让他去执行。
主键索引的根页
一个以name为索引的B+TREE
free链表用于存放未被占用的缓存数据页,启动mysql时空的,磁盘数据通过这个链表对buffer poll中的空数据也寻址,在数据被刷盘到磁盘文件后对应的缓存会空闲,free链表也会将空闲缓存也的数据描述添加进来
redo log block'总大小512字节
name字段非主键这边是一个非聚簇索引B+TREE
name=b
磁盘加载到缓存
IO调度层默认是用CFQ公平调度算法的
redolog并不一条数据一条数据的刷入磁盘,而是将body体的内存用后后一次性输入磁盘每个增删改都是一个redolog,当一个事务有多个redolog时,多个redulog作为一个redolog组,而在同一个redologblock放不下时那就可能放入到其他几个redologblock中同样当一个redologgroup比较小,也可能多个redulog组放入同一个redologblock
索引页号=50
表ID在那个表里插入数据
TRX_UNDO_INSERT_REC重新定位,并新增一条记录插到聚簇索引中
bigintnull
最小id=98
后台IO线程不是在bufferpol内,只是没地方画了
叶节点
6准备提交事务,binlog准备刷盘
数据页号=100
数据页页号1
最小id=50
最小id=95
一行数据结构
磁盘
索引页号=40
被索引的各列的位置/占用空间/值
表空间号 + 数据页号 = key, 缓存页地址=value
第一组数据区的第一个数据区的前3个数据页,都是固定的,里面存放了一些描述性的数据
查找主键对应的一条数据只需要使用二分查找就可以比较简单的定位数据在哪个数据页,定位数据页后在通过二分查找数据行就可以找到具体数据了
index_col_info len
undo type
表空间tablename.ibd文件
索引页号=21
bufferpoll
数据页目录
redolog log
undolog日志结束位置
innodb_flush_log_at_trx_commit =1redolog直接刷盘redolog文件内多个redologblck的数据结构存储参数innodb_log_group_home_dir可以设置redolog文件路径解决redolog文件占用磁盘或者文件太小内容信息不都的情况可以通过参数innodb_log_file_size(默认48mb)和innodb_log_file_in_group(默认2个文件)两个参数来限制redolog的大小和日志分片的数量
空闲区域
sync_binlog=0默认为1不直接刷盘,而是先进入oscache
表空间文件
定时刷新,整页刷入数据页的大小是固定的,因此刷盘时只要获取startposition和endposition之间的数据就可以了
buffer poll一块连续的内存
索引页页号50
char(1)1
innodb_flush_log_at_trx_commit =2redolog先计入oscache
id=5
7binlog刷盘并发送commit给redolog
TRX_UNDO_UPD_EXIST_REC
2个字节的first record group。这个是说每个事务都会有多个redo log,是一个redo log group,即一组redo log。那么在这个block里的第一组redo log的偏移量,就是这2个字节存储的;
checkpoint no 4字节
索引页号=2
最小id=7
chunk
index_col_info len
VFS层接收mysql进程的磁盘读写
不更新主键
undolog日志起始位置
数据描述1空缓存
表空间号 + 数据页号 = key, 缓存页地址=value
0x09 0x04 00000101 0000000000000000000010000000000000011001 00000000094C(DB_ROW_ID)00000000032D(DB_TRX_ID) EA000010078E(DB_ROL_PTR) 616161 636320 6262626262
数据页号=99
最小主键=95
数据页页号=100
这一整个主键索引的B+ TREE就是一个聚簇索引
sync_binlog=1直接刷盘
如果redolog文件已经存在比较多的redologblck此时要在磁盘的某个位置找到一个redologblock修改几个字节数据直接通过磁盘IO写入磁盘(画不下了,就不指向磁盘IO流程了),这就是磁盘随机写
块编号(block no) 4字节
索引页号=1
字段值根据字符集编码转换成一些数字和符号后存储
生成顺序
flush刷盘队列,更新的数据翻入flush,等待IO线程刷盘
5redolog刷盘
可能只是一个id也可能是多个字段的联合主键
数据页页号=2
InnoDB需要对聚簇索引进行处理
name=e
body(496字节)
文件尾部(8字节)
0 条评论
回复 删除
下一页