Innodb存储引擎特性:
DoubleWrite
Insert/Change Buffer
Adaptive Hash Index
Flush neighbor page
DoubleWrite:
(root@DB)[information_schema]> showvariables like '%double%'
-> ;
+--------------------+-------+
| Variable_name | Value |
+--------------------+-------+
| innodb_doublewrite | ON |
+--------------------+-------+
1 row in set (0.01 sec)
目的:数据写入页的可靠性(默认开启)
主要解决以下问题:
Partial write(部分写):一个页只写了部分的内容,这时数据库宕机了
16K的页只写入了4k,6k,8k,12K的情况
不可以通过redo log进行恢复,因为页的数据不完整,页已损坏
Like Oracle media corrupt
保证redo的数据是完整的,一致的,doublewrite就是用来保证redo页的完整
工作原理
doublewrite固定存放在ibdate共享表空间中
存在一个段对象doublewrite中
2M大小(both fileand memory),不可修改,由两个区组成
页在刷新时首先顺序写入到doublewrite
然后再刷新回磁盘
doublewrite采用覆盖写,本次的写入会覆盖上次的数据,2M数据是覆盖写入的,先写doublewrite,再写数据文件。一份数据写两份,有个保障,其中一份如果页有损坏,可以用另一份来恢复页的数据
如果写数据页时,共享表空间的页损坏了,mysql就会以数据文件中的页为准
如果写数据页时,数据文件中的页损坏了,mysql就会以共享表空间中的页为准
性能开销:
doublewrite 写入是顺序的
性能开销取决于写入量
通常5%-25%
slave服务器不能关闭doubelwrite
可关闭doublewrite的条件:
1.atomic write
磁盘
Fusion-IO #支持原子写
文件系统
ZFS(solaries操作系统的文件系统) ,#linux系统不可用
btrfs #linux系统不可用
--skip-innodb-doublewrite #关闭doublewrite
Insert/Change Buffer
Insert buffer
用来提高辅助索引的插入性能,减少随机IO,一次性合并插入
nono unique secondary index
Insert Buffer对象在共享表空间中,在ibdata文件中,写insert buffer时也会写redo日志
原理:
先把插入二级索引的值先缓存起来,放到Insert buffer对象中,如果要查询到二级索引时,再将Insert buffer对象中的页再一次性合并到原表中
先判断插入的非聚集索引页码是否在缓冲池中,若中,则直接插入
若不在,则先放入到一个Insert buffer对象中
insert buffer 也是一颗B+树
每次最多缓存2K的记录
当读取辅助索引页码到缓冲池,将Insert Buffer中该页的记录合并到辅助索引页
(root@DB)[information_schema]> show variables like'%change%'
-> ;
+-------------------------------+-------+
| Variable_name | Value |
+-------------------------------+-------+
| innodb_change_buffer_max_size | 25 | #insert buffer大小最大为bufferpool的25%
| innodb_change_buffering |all | #默认值是打开的
| session_track_state_change |OFF |
+-------------------------------+-------+
3 rows in set (0.00 sec)
create table t (
a int auto_increment,
b varchar(30),
primary key(a)
)
create table t(
a int auto_increment,
b varchar(30),
primary key(a),
key(b)
)
Insert buffer用于提升b列的插入性能,通过空间换时间来提高
潜在问题
最大可以使用1/2缓冲池内存
--innodb-change-buffer-max-size=25
shutdown 不进行insert buffer记录合并
insert buffer开始进行合并时插入性能开始下降
(root@DB)[information_schema]> show engine innodbstatus\G;
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 0, delete mark 0, delete 0
discarded operations:
insert 0, delete mark 0, delete 0
seg size:占用页的数量,这个占用了2个页
merges:合并了多少个页
insert:插入了多少条记录
discarded operations:当表的数据插入到insert buffer之后,这张表被删除了,那insert buffer里面的数据就没有用了,discarded表示丢弃的页记录
Change Buffer:
insert buffer:只能对insert进行缓存,change buffer可以对所有的操作进行cache
insert
Delete-marking
Purge
-- innodb_change_buffering
all
None
inserts
Deletes
Changes=(insert & delete-marking)
Purges
(root@DB)[(none)]> show engine innodb status\G;
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
insert 2323233, delete mark 4234234, delete4213
discarded operations:
insert 0, delete mark 0, delete 0
Adaptive Hash Index
5.6以上的版本建议关闭Adaptive Hash Index
CPU占用会高,但性能没有提升
查找buffer pool中页是否是活跃的页,如果是活跃的页,则mysql会自动对页进行hash,不需要手动干预
搜索时间复杂度
B+树 #只能查找以页,不能找出页中的记录
哈希表 #可以直接找出页中的记录
(root@DB)[(none)]> show variables like'%innodb_adaptive%';
+----------------------------------+--------+
| Variable_name | Value |
+----------------------------------+--------+
| innodb_adaptive_flushing | ON |
| innodb_adaptive_flushing_lwm |10 |
| innodb_adaptive_hash_index |ON |
| innodb_adaptive_hash_index_parts | 8 | #分片,这里是8个分片
| innodb_adaptive_max_sleep_delay | 150000 |
+----------------------------------+--------+
5 rows in set (0.00 sec)
(root@DB)[(none)]> show engine innodb status\G;
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
Hash table size 34673, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
Flush neighbor page
目的:将随机的访问,转换为顺序的访问
Flush Neighbor Page(FNP)
试图刷新页所在区中的所有脏页
传统机载磁盘有效
SSD关闭此功能,配置值为0
MYSQL 5.6
--innodb_flush_neighbors=1|0
(root@DB)[(none)]> show variables like'%neighbor%'
-> ;
+------------------------+-------+
| Variable_name | Value|
+------------------------+-------+
| innodb_flush_neighbors | 1 |
+------------------------+-------+
1 row in set (0.01 sec)
参数值:
0:表示关闭
1表示打开
2表示只刷新连续的页
可以在线修改:
(root@DB)[(none)]> set globalinnodb_flush_neighbors=0;
Query OK, 0 rows affected (0.00 sec)