swap分析及行溢出分析ml

本文涉及的产品
云数据库 RDS MySQL Serverless,0.5-2RCU 50GB
简介:

swap out:把内存中暂时不用的数据交换出去,放在swap分钟

swap in:把swap分区中的数据交换会物理内存中

vmstat -S m 1


[root@nod2 ~]# vmstat -S m 1

procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----

 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st

 0  0     33  21278    211   1978    0    0     2     5    0    0  1  0 99  0  0

 1  0     33  21278    211   1978    0    0     0    68 1079 1792  0  0 99  0  0

 1  0     33  21278    211   1978    0    0     0    24  987 1613  0  0 100  0  0

 0  0     33  21277    211   1978    0    0     0    64  935 1570  0  0 100  0  0

 0  0     33  21277    211   1978    0    0     0    64 1108 1843  0  0 99  0  0

 1  0     33  21277    211   1978    0    0     0    40  842 1390  0  0 100  0  0

 0  0     33  21276    211   1978    0    0     0    24 1086 1586  0  0 100  0  0

 0  0     33  21276    211   1978    0    0     0    80  979 1658  0  0 99  1  0


发生的原因:

最直接原因可能是进程向OS申请内存时,发现物理内存不足:这时会一直等待(dirty page未flush),swap,可能发生oom-killer机制

和内核选项vm.swappiness有关系,参数可选范围从0--100,设置为0就是希望最大使用物理内存,尽量不使用SWAP,设置为100,则希望积极使用SWAP

数据库可以设置成为5到10范围。若有高可用,直接设置为0


[root@nod2 ~]# top

top - 10:30:07 up 7 days, 16:55,  3 users,  load average: 0.11, 0.12, 0.09

Tasks: 335 total,   1 running, 334 sleeping,   0 stopped,   0 zombie

Cpu(s):  0.5%us,  0.1%sy,  0.0%ni, 99.2%id,  0.2%wa,  0.0%hi,  0.0%si,  0.0%st

Mem:  24591004k total,  3812944k used, 20778060k free,   206792k buffers

Swap:  4194300k total,    419400k used,  300k free,  1932400k cached


1、物理内存有空闲,但使用了SWAP

查看物理内存分配free -gt 

[root@nod2 ~]# free -gt

 total       used       free     shared    buffers#缓冲写入的内存快(脏数据)     cached#缓存热数据 used=shared+buffers+cached

Mem:            23          3         19          0          0          1

-/+ buffers/cache:          1         21

Swap:            3          3          0

Total:          27          3         23

1、典型内存泄露(memory leak),cached和used相差特别大,基本可以确定系统发生ml

解决办法:治标:重启机器

治本:升级版本、提交BUG

发生SWAP原因:

内存不够,IBP分配够大,numa设置问题

查看numa相关情况:

numactl --show


如何避免numa

1、在BIOS设置层面关闭numa,缺点需要重启os

2、修改grup配置文件,重启OS

3、升级MySQL版本到5.6.27版本,新增了一个选项innodb_numa_interleave,


正确认识InnoDB

基于B+树结构的聚集索引组织表

   聚集索引优先选择显示定义的主键

   其次选择第一个非NULL的唯一索引

   再次使用隐藏的ROWID

   聚集索引叶子节点存储整行数据

InnoDB默认是行锁,是在索引记录上加锁实现行锁机制


innodb表都要有一个主键,且主键最好没有业务用途,不要修改主键值

主键最好保持顺序递增,随机主键值会导致聚集索引树频繁分裂,随机I/O增多,数据离散,性能下降

没有索引的更新,可能会导致全表数据都被锁住,和表级锁等同后果

定义列属性时,长度预估够用就好,没必要用特别大的数据类型。

varchar/text等数据类型实际存储长度越小越好,否则发生行溢出(off-page-storage)时对性能影响可能很大

不超过255字节的,

页(PAGE)是innoDB存储引擎的最小存储单位,默认大小为16KB,及16384字节,行数据存储在页中

一行数据为多大时,会发生行溢出呢?我们知道InnoDB存储引擎表是索引组织的,即B+树结构,这样一个页中至少要保证有2条数据,否则就变成链表了,如果只能存放一条数据,

那么InnoDB存储引擎会自动将它存放在溢出页中。如果可以在一个页中至少放入两行数据,那么就不会发生行溢出

其实对于BLOB类型的数据,跟varchar也是一个道理,要看实际的大小,当然,用户既然使用了blob列类型,一般不可能存放长度过小的数据,因此在大多数情况下BLOB的行数据还是会发生行溢出,

实际数据保存在BLOB页中,数据页只保存数据的前768字节


不要直接select * 读取全部列,可能会导致更多的I/O读




表空间:INNODB 所有数据都存在表空间当中(共享表空间),要是开启innodb_file_per_table,则每张表的数据会存到单独的一个表空间内(独享表空间)。

独享表空间包括:数据,索引,插入缓存,数据字典。共享表空间包括:Undo信息(不会回收<物理空间上>),双写缓存信息,事务信息等。

段(segment):组成表空间,有区组成。

区(extent):有64个连续的页组成。每个页16K,总共1M。对于大的数据段,每次最后可申请4个区。

页(page):是INNODB 磁盘管理的单位,有行组成。

行(row):包括事务ID,回滚指针,列信息等。


#####

测试表空间

表空间各个页的信息和溢出行数据存储的信息。通过该书作者蒋承尧编写的工具

首先把3个脚本的放在同一个目录下

http://down.51cto.com/data/2264077#脚本

测试1:

create table tt(id int auto_increment,name varchar(10),age int,address varchar(20),primary key (id))engine=innodb;

然后查看tt表ibd的信息

[root@nod1 dbtest]# python py_innodb_page_info.py /home/mysql3306/mysql3306/test/tt.ibd -v

page offset 00000000, page type <File Space Header>

page offset 00000001, page type <Insert Buffer Bitmap>

page offset 00000002, page type <File Segment inode>

page offset 00000003, page type <B-tree Node>, page level <0000> ##叶子节点

page offset 00000000, page type <Freshly Allocated Page>

page offset 00000000, page type <Freshly Allocated Page>

Total number of page: 6:  #总页数

Freshly Allocated Page: 2 #可用页数

Insert Buffer Bitmap: 1   #插入缓存位图页

File Space Header: 1      

B-tree Node: 1            #数据节点 

File Segment inode: 1     


上面得到的信息是表初始化大小为96K,他是有 Total number of page * 16 得来的。1个数据页,2个可用页面。

区是64个连续的页,大小1M。那么表大小也应该是至少1M。但是现在只有96K(默认)。原因是因为每个段开始的时候,

先有32个页大小的碎片页存放数据,使用

完之后才是64页的连续申请,最多每次可以申请4个区,保证数据的顺序。

这里看出表大小增加是按照至少64页的大小的空间来增加的,即1M增加。


[root@nod1 dbtest]# python py_innodb_page_info.py /home/mysql3306/mysql3306/test/tt.ibd -v

page offset 00000000, page type <File Space Header>

page offset 00000001, page type <Insert Buffer Bitmap>

page offset 00000002, page type <File Segment inode>

page offset 00000003, page type <B-tree Node>, page level <0000>

page offset 00000000, page type <Freshly Allocated Page>

page offset 00000000, page type <Freshly Allocated Page>

Total number of page: 6:

Freshly Allocated Page: 2

Insert Buffer Bitmap: 1

File Space Header: 1

B-tree Node: 1

File Segment inode: 1


溢出行数据存放:INNODB存储引擎是索引组织的,即每页中至少有两行记录,

因此如果页中只能存放一行记录,INNODB会自动将行数据放到溢出页中。当发生溢出行的时候,实际数据保存在BLOB页中,数据页只保存数据的前768字节(老的文件格式),新的文件格式(Barracuda)采用完全行溢出的方式

,数据页只保存20个字节的指针,BLOB也保存所有数据。如何查看表中有溢出行数据呢?

create table t1 (id int,name varchar(10),memo varchar(8000))engine =innodb default charset utf8;

insert into t1 values(1,'zjy',repeat('我',8000));

[root@nod1 dbtest]# python py_innodb_page_info.py /home/mysql3306/mysql3306/test/t1.ibd -v

page offset 00000000, page type <File Space Header>

page offset 00000001, page type <Insert Buffer Bitmap>

page offset 00000002, page type <File Segment inode>

page offset 00000003, page type <B-tree Node>, page level <0000>

page offset 00000004, page type <Uncompressed BLOB Page>

page offset 00000005, page type <Uncompressed BLOB Page>

Total number of page: 6:

Insert Buffer Bitmap: 1

Uncompressed BLOB Page: 2

File Space Header: 1

B-tree Node: 1

File Segment inode: 1


从信息中看到,刚才插入的一行记录,已经溢出了,保存到了2个BLOB页中(<Uncompressed BLOB Page>)。

因为1页只有16K,又要存2行数据,所以每行记录最好小于8K,

而上面的远远大于8K,所以被溢出了。当然这个也不是包括特大字段,要是一张表里面有5个字段都是varchar(512)

【多个varchar的总和大于8K就可以】,也会溢出:


1000+500+500+500+500+500=3500*3>8000字节;行会被溢出

root@nod1 dbtest]# python py_innodb_page_info.py /home/mysql3306/mysql3306/test/t2.ibd -v

page offset 00000000, page type <File Space Header>

page offset 00000001, page type <Insert Buffer Bitmap>

page offset 00000002, page type <File Segment inode>

page offset 00000003, page type <B-tree Node>, page level <0000>

page offset 00000004, page type <Uncompressed BLOB Page>

page offset 00000000, page type <Freshly Allocated Page>

Total number of page: 6:

Insert Buffer Bitmap: 1

Freshly Allocated Page: 1

File Segment inode: 1

B-tree Node: 1

File Space Header: 1

Uncompressed BLOB Page: 1


<Uncompressed BLOB Page> 页存放真正的数据,那数据页到底存放什么?用hexdump查看:


 hexdump -C -v /home/mysql3306/mysql3306/test/t1.ibd >t2.txt

目的2:

     了解表空间如何存储数据,以及对NULL值的存储。

在测试前先了解INNODB的存储格式(row_format)。老格式(Antelope):Compact<默认>,Redumdant;新格式(Barracuda):Compressed ,Dynamic。

这里测试指针对默认的存储格式。

Compact行记录方式如下:

|变长字段长度列表(1~2字节)|NULL标志位(1字节)|记录头信息(5字节)|RowID(6字节)|事务ID(6字节)|回滚指针(7字节)|

上面信息除了 "NULL标志位"[表中所有字段都定义为NOT NULL],"RowID"[表中有主键] ,"变长字段长度列表" [没有变长字段] 可能不存在外,其他信息都会出现。

、所以一行数据除了列数据所占用的字段外,还需要额外18字节。



一:字段全NULL

mysql> use test;

Reading table information for completion of table and column names

You can turn off this feature to get a quicker startup with -A


Database changed

mysql> create table mytest(t1 varchar(10),t2 varchar(10),t3 varchar(10) ,t4 varchar(10))engine=innodb charset = latin1 row_format=compact;

Query OK, 0 rows affected (0.02 sec)


mysql> insert into mytest values('a','bb','bb','ccc');

Query OK, 1 row affected (0.00 sec)


mysql> insert into mytest values('a','ee','ee','fff');

Query OK, 1 row affected (0.01 sec)


mysql>  insert into mytest values('a',NULL,NULL,'fff');

Query OK, 1 row affected (0.00 sec)



测试数据准备完之后,执行shell命令:




3080 0000c070  73 75 70 72 65 6d 75 6d   03 02 02 01 00 00 00 10  |supremum........|

3081 0000c080 00 25 00 00 00 00 02 05  00 00 00 01 3c ac b1 00  |.%..........<...|

3082 0000c090  00 01 6b 01 10 61 62 62  62 62 63 63 63 03 02 02  |..k..abbbbccc...|

3083 0000c0a0  01 00 00 00 18 00 23 00  00 00 00 02 06 00 00 00  |......#.........|

3084 0000c0b0  01 3c ad b2 00 00 01 db  01 10 61 65 65 65 65 66  |.<........aeeeef|

3085 0000c0c0  66 66 03 01 06 00 00 20  ff a6 00 00 00 00 02 07  |ff..... ........|

3086 0000c0d0  00 00 00 01 3c b2 b5 00  00 02 fe 01 10 61 66 66  |....<........aff|

3087 0000c0e0  66 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |f...............|

3088 0000c0f0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|

第一行数据:

03 02 02 01 /*变长字段*/ ---- 表中4个字段类型为varchar,并且没有NULL数据,而且每个字段君小于255。

00 /*NULL标志位,第一行没有null的数据*/

00 00 10 00 25 /*记录头信息,固定5个字节*/

00 00 00 00 02 05 /*RowID,固定6个字节,表没有主键*/

00 00 00 01 3c ac /*事务ID,固定6个字节*/

b1 00 00 01 6b 01 10 /*回滚指针,固定7个字节*/

61 62 62  62 62 63 63 63 /*列的数据*/

第二行数据和第一行数据一样(颜色匹配)。

第三行数据(有NULL值)和第一行的解释的颜色对应起来比较差别:


03 02 02 01  VS  03 01   ----------当值为NULL时,变长字段列表不会占用存储空间。

61 62 62  62 62 63 63 63 VS 61 66 66 66  --------- NULL值没有存储,不占空间

结论:当值为NULL时,变长字段列表不会占用存储空间。NULL值没有存储,不占空间,但是需要一个标志位(一行一个)。


本文转自 DBAspace 51CTO博客,原文链接:http://blog.51cto.com/dbaspace/1878136

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
人工智能 算法 数据可视化
R语言DTW(Dynamic Time Warping) 动态时间规整算法分析序列数据和可视化
R语言DTW(Dynamic Time Warping) 动态时间规整算法分析序列数据和可视化
11 0
|
5月前
|
存储 Java BI
JVM内存溢出深度分析
JVM内存溢出深度分析
49 0
|
8月前
模拟实现库函数memcpy--复制内存块。详细理解内存重叠及精准复制问题
模拟实现库函数memcpy--复制内存块。详细理解内存重叠及精准复制问题
|
11月前
|
机器学习/深度学习 自动驾驶 算法
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!(一)
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!(一)
153 0
|
11月前
|
算法 计算机视觉
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!(二)
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!(二)
66 0
|
SQL Oracle 关系型数据库
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
本篇文章讲解的主要内容是:***计算部门中那个工资等级的员工最多、通过返回部门10最大工资所在行的员工名称小案例来讲解max/min() keep() over()、通过查询工资最高的人小案例来介绍fisrt_value、last_value、通过计算各个部门的工资合计以及各个部门合计工资占总工资的比例小案例来介绍如何计算百分比及ratio_to_report分析函数的使用***
【SQL开发实战技巧】系列(十五):查找最值所在行数据信息及快速计算总和百之max/min() keep() over()、fisrt_value、last_value、ratio_to_report
|
机器学习/深度学习 自动驾驶 算法
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!
364 0
3D检测经典 | 第一个Anchor-Free、第一个NMS-Free 3D目标检测算法!!!
|
Linux
内核笔记](四)——内核常见调试手段(printf、dump_stack、devmem)
内核笔记](四)——内核常见调试手段(printf、dump_stack、devmem)
182 0
内核笔记](四)——内核常见调试手段(printf、dump_stack、devmem)
分段线性 DP 问题,以及常见空间优化手段|Java 刷题打卡
分段线性 DP 问题,以及常见空间优化手段|Java 刷题打卡
SAP QM初阶之取样策略如何确定检验批Sample Size?
SAP QM初阶之取样策略如何确定检验批Sample Size?
SAP QM初阶之取样策略如何确定检验批Sample Size?