MySQL优化-InnoDB存储引擎

MySQL优化-InnoDB存储引擎

InnoDB简介
    和Oracle很相似。
    基于B+树的聚集索引的IOT表。
    支持行锁(基于索引实现)。
    支持ACID、MVCC、Crash Recovery等特性。
    支持4种事务隔离级别,RR下可以避免幻读。
    支持外键、全文检索。
    支持多种文件格式及数据压缩。
    高性能、高并发、高效的buffer pool管理。


log buffer = redo log buffer
dirty page 对innodb表修改的数据页先放在这里。
free page 还没有被使用的空闲内存页。
cache page 缓存读出来还没有被修改的热点数据。
undo log 数据被修改之前,旧版本数据会放在这里。


存储结构
    系统表空间文件ibdata*
    通用表空间文件*.ibd
    用户表空间文件*.ibd
    全文索引fts*ibd
    全局undo log、用户自定义undo log *.ibu
    redo log
    全局、会话级临时表空间文件(ibtmp1、*.ibt)
    buffer pool dump file
    innodb stauts file


tablespace,表空间
    表存储对象。
    每个tablespace都至少包含2种segment(叶子/非叶子page file segment)
segment,段
    对象单位,例如rollback seg,undo seg,index seg等。
    每个segment由n个extent以及32个零散page组成。
    segment最小以extent为单位扩展。
extent,簇/区
    空间管理单位。
    每个extent为1/2/4MB,由n个page组成。
page,页
    最小I/O单位,16KB,5.6版本起可自定义page size。


表空间
    所有的数据都需要存储在表空间中。
    表空间分类:
        系统表空间
        用户独立表空间
        undo tablespace,MySQL 5.6+
        temporary tablespace,MySQL 5.7+
        general tablespace,MySQL 5.7+


系统表空间
    总是必须的
    文件名ibdata1, ibdata2, ibdata3, ...
    innodb_data_home_dir  = /data/mysql/3306/innodb_ts
    innodb_data_file_path = /data/mysql/3306/innodb_ts/ibdata1:100M:autoextend
    随着undo space分离出去,初始化大小100MB左右就够用了。
    写多个ibdataN的格式是加分号;
        ibdata1:100M:autoextend;ibdata2:100M:autoextend;ibdata3:100M:autoextend
    主要存储对象
        data dictionary
        double write buffer
        insert buffer/change buffer
        rollback segments
        undo space
        foreign key constraint system tables
        user data,if innodb_file_per_table = 0


用户独立表空间
    innodb_file_per_table = 1(默认)
    innodb_file_per_table = 0 共享表空间,用户数据存储在系统表空间ibdataN文件中,或者自定义的通用表空间general tablespace中。
    存储聚集索引(row data)以及辅助普通索引数据。
    每个table都有各自的.ibd文件。
    rollback segments,doublewrite buffer,change buffer等仍存储在系统表空间文件里。
    表空间可更方便回收。
    透明表空间文件迁移。
    不过需要更多的file handler,当table数量很大(尤其是很多表分区)时,可能会是个麻烦。
    删除大表时的代价也更大。


通用表空间,general tablespace
    类似Oracle的做法。
    多个table放在同一个表空间中。
    可以定义多个通用表空间,并且分别放在不同磁盘上。
    可以减少metadata的存储开销。
    和系统表空间类似,已分配的表空间无法收缩归还给操作系统(需重建)
    8.0后,所有metadata都存储在mysql这个通用表空间中。
    create tablespace ts01 add datafile 'ts01.ibd' engine=innodb;
    create table app01.t1(id int) tablespace ts01 row_format=dynamic engine=innodb;
    select * from information_schema.innodb_tablespaces where name='ts01'\G
    show create table app01.t1\G


undo表空间
    管理回滚段和undo log。
    实例初始化时,默认创建两个undo表空间,最大127个。
    可以在线被truncate,因此最少需要两个undo表空间。
    选项innodb_rollback_segments用于定义每个undo表空间中的回滚段数量,默认是(即最大值) 是128个。
    支持undo表空间加密。
    8.0.14后,可以在线手动创建新的undo表空间。
    create undo tablespace undo_03 add datafile 'undo_03.ibu';
    mysqladmin var | grep -i undo
    mysqladmin var | grep -i rollback
    移动undo表空间文件
        用户自行创建的undo表空间,在实例重启期间可以进行移动(只要目录能被InnoDB识别)。
        如果想移动系统自动创建的两个undo表空间,则需要在实例重启后,同时修改选项innodb_undo_directory指向的路径。
        实例启动时,会自动扫描数据目录下的undo表空间文件。
    MySQL实例启动过程中,会去扫描以下目录:
        扫描顺序 innodb_directories、innodb_data_home_dir、datadir、innodb_undo_directory。
    查看undo表空间
        select * from information_schema.innodb_tablespaces where name='undo_01';
        select * from information_schema.files where file_type='undo log';
    手动在线删除undo表空间
        1.先设置不活跃
        alter undo tablespace undo_03 set inactive;
        2.而后再删除
        drop undo tablespace undo_03;
    innodb_undo_log_truncate = ON 时会自动清理undo表空间。
        超过innodb_max_undo_log_size时会触发。
        或purge线程执行了innodb_purge_rseg_truncate_frequency(128)次。


全局临时表空间,global temporary tablespace
    ibtmp1文件。
    存储用户临时表的rollback segment。
    用户session断开,或删除临时表后,回滚段会删除释放,但表空间不会自动收缩归还给OS,需要等到重启后自动重建。
    innodb_temp_data_file_path选项定义路径、大小等,初始值12MB。
    限制其最大尺寸会造成无法创建临时表,或者大SQL执行过程中报错。
    实例关闭后,文件会被删除;实例启动后,文件重新创建。
    无需参与crash recovery,因此也不记录redo logselect * from information_schema.files where tablespace_name='innodb_temporary'\G


会话级临时表空间,session temporary tablespace
    存储用户创建的临时表,及用户执行sql过程中生成的内部(磁盘)临时表。
    internal_tmp_disk_storage_engine 设置内部磁盘临时表引擎类型,8.0.16开始强制用InnoDB,该选项也随之失效。
    innodb_temp_tablespace_dir = "./#innodb_tmp/" 选项设置会话级用户临时表空间存储路径。
    会话级临时表空间(池)初始共有10个,会随着用户连接数及创建临时表的情况按需增加。实例重启后会删除这些文件。
    每个session随机分配到某个临时表空间中,例如A用户连接后分配到temp_1.ibt,B用户连接后分配到temp_2.ibt。
    每个session最多分配两个临时表空间,一个用于存储用户主动创建的临时表(create temporary table),另一个用于存储用户执行sql过程中生成的内部(磁盘)临时表。
    session断开后,会话级用户临时表空间会直接释放,不用再担心撑爆磁盘。
    select * from information_schema.innodb_session_temp_tablespaces;
    show processlist;
    select * from information_schema.innodb_temp_table_info;


共享表空间模式(不推荐使用)
    设置innodb_file_per_table = 0
    用户数据存储在系统表空间ibdata*文件中,或者自定义的通用表空间(general tablespace)中。
    删除大表或删除大量数据时开销更小,drop table / truncate table。
    可以使用裸设备,据称性能可能有提升。


删除大表方法:
    1.硬链接 ln x.ibd y.ibd
    2.执行drop
    3.删除y.ibd


查看数据表碎片率
    Data_length + Index_length + Data_free, 对比物理ibd文件实际大小。
    或者,Rows *  Avg_row_length, 对比物理ibd文件实际大小。
    5.7.5开始增加选项innodb_fill_factor,可设置100提高填充率。
    碎片率 = 1 - 理论大小/实际大小,碎片率大于30%认为碎片率很高。
[dba@localhost:mysql.sock] [app01]> show table status like 't1'\G
*************************** 1. row ***************************
           Name: t1
         Engine: InnoDB
        Version: 10
     Row_format: Dynamic
           Rows: 0
 Avg_row_length: 0
    Data_length: 16384
Max_data_length: 0
   Index_length: 0
      Data_free: 0
 Auto_increment: 2
    Create_time: 2019-12-16 10:58:35
    Update_time: NULL
     Check_time: NULL
      Collation: utf8mb4_general_ci
       Checksum: NULL
 Create_options: 
        Comment: 
1 row in set (0.01 sec)


降低数据表碎片,回收表空间
    独立表空间
        alter table ** engine = innodb;
        optimize table **;
        尽量用pt-osc/gh-ost来操作。
    共享表空间
        整个实例重新逻辑备份导出,再导入。
        最好是初始化时,就提前规划系统表空间尺寸,避免后期暴涨。


表空间文件迁移
    目标服务器上:alter table xx discard tablespace;
    源服务器上:flush table x for export; 备份过去
    目标服务器上:alter table xx import tablespace;
    表结构务必一致。
    innodb_page_size也要一致。


数据在page里是怎么组织存储的,理解从page到row的概念。
page,页(不建议调整)
    最小I/O单位,默认16KB。
    innodb_page_size
        <5.6版本时,不可调整。
         5.6版本时,可自定义为8KB、4KB,但不能调大。
         5.7以上,才可以改成32KB,64KB。
         全局选项,无法在运行过程中动态修改,实例初始化后也无法再修改。
    # innblock ./app01/t1.ibd scan 16

cp -a t1.ibd /tmp/
vim -b /tmp/t1.ibd
:%!xxd
或者hexdump -C -v /tmp/t1.ibd | less

row_format
    Redundant,最早的行格式。
    Compact,将长字段超过768字节的部分off-page存储,5.0之后的默认行格式。
    Dynamic,将长字段完全off-page存储,5.7之后的默认行格式。
    Compressed,将data、index pages进行压缩,但buffer pool中的page则不压缩(Compressed模式压缩比约1/2,MySQL 5.1期间测试tps下降到原来的1/10,影响巨大;MySQL 5.7版本测试性能相差不大,有时甚至更好。建议自行实际测试后再决定)。
    查看行格式:show table status 或查看元数据。
[dba@localhost:mysql.sock] [(none)]> show table status from app01;
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+-----------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation          | Checksum | Create_options | Comment   |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+-----------+
| t1   | InnoDB |      10 | Dynamic    |    4 |           4096 |       16384 |               0 |            0 |         0 |              5 | 2020-04-12 17:43:24 | NULL        | NULL       | utf8mb4_general_ci |     NULL |                | 测试表    |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+--------------------+----------+----------------+-----------+
1 row in set (0.00 sec)


行溢出,overflow(行迁移、行链接)
    行记录长度大约超过page一半时,依次将最长的列拆分到多个page存储,直到不再超过page的一半为止。
    溢出的列放在一个page中不够的话,还会继续放在新的page中。
    Compact格式下,溢出的列只存储前768字节。
    Dynamic格式下,溢出的列只存储前20字节(指针)。
    select * 会同时读取这些溢出的列,因此代价很高。
    text列上出现filesort或temporary table时,一般都无法放在内存中,需要变成disk tmp table,I/O代价更高。

行格式
    默认采用Dynamic格式即可。
    少用blob/text长字段类型。
    少用select *。


InnoDB表数据字典有2份。
    server层,frm文件。
        DDL过程中crash的话,有可能会来不及刷新,导致元数据不一致,sync_frm=18.0起全部存储在InnoDB引擎中。
    InnoDB层
        InnoDB_SYS_DATAFILES
        InnoDB_SYS_TABLESTATS
        InnoDB_SYS_INDEXES
        InnoDB_SYS_FIELDS
        InnoDB_SYS_TABLESPACES
        InnoDB_SYS_FOREIGN_COLS
        InnoDB_SYS_FOREIGN
        InnoDB_SYS_TABLES
        InnoDB_SYS_COLUMNS

工具:innblock、innodb_ruby


InnoDB内存结构
buffer pool 怎么设置才合理,理解InnoDB的内存管理机制。
在有的文章里写着LRU list、flush list、free list。
    LRU list   = page cache
    flush list = dirty page
    free list  = free page
innodb内存组织:
    innodb_buffer_pool : page cache、dirty page、free page、change buffer、double write buffer、page hash、adaptive hash index、lock system、file system、dictionary cache、recovery system。
    redo log buffer


查看表的数据和索引使用情况
select engine, count(*) as TABLES,
    concat(round(sum(table_rows)/1000000,2),'M') rs,
    concat(round(sum(data_length)/(1024*1024*1024),2),'G') DATA,
    concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx,
    concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size,
    round(sum(index_length)/sum(data_length),2) idxfrac
from information_schema.TABLES
where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'test')
group by engine
order by sum(data_length+index_length)
desc limit 10;

[dba@localhost:mysql.sock] [(none)]> select engine, count(*) as TABLES,
    ->     concat(round(sum(table_rows)/1000000,2),'M') rs,
    ->     concat(round(sum(data_length)/(1024*1024*1024),2),'G') DATA,
    ->     concat(round(sum(index_length)/(1024*1024*1024),2),'G') idx,
    ->     concat(round(sum(data_length+index_length)/(1024*1024*1024),2),'G') total_size,
    ->     round(sum(index_length)/sum(data_length),2) idxfrac
    -> from information_schema.TABLES
    -> where table_schema not in ('mysql', 'performance_schema', 'information_schema', 'test')
    -> group by engine
    -> order by sum(data_length+index_length)
    -> desc limit 10;
+--------+--------+-------+-------+-------+------------+---------+
| engine | TABLES | rs    | DATA  | idx   | total_size | idxfrac |
+--------+--------+-------+-------+-------+------------+---------+
| InnoDB |     28 | 0.05M | 0.00G | 0.00G | 0.01G      |    0.50 |
| NULL   |    107 | NULL  | NULL  | NULL  | NULL       |    NULL |
+--------+--------+-------+-------+-------+------------+---------+
2 rows in set (0.24 sec)

查看buffer pool中共有多少个page
[dba@localhost:mysql.sock] [(none)]> select count(*) from information_schema.innodb_buffer_page;
+----------+
| count(*) |
+----------+
|     6400 |
+----------+
1 row in set (0.03 sec)

查看buffer pool的组成
[dba@localhost:mysql.sock] [(none)]> select page_type as Page_Type,
    ->     sum(data_size)/1024/1024 as Size_in_MB
    -> from information_schema.innodb_buffer_page
    -> group by Page_Type
    -> order by Size_in_MB desc;
+-------------------+------------+
| Page_Type         | Size_in_MB |
+-------------------+------------+
| INDEX             | 1.08798695 |
| IBUF_INDEX        | 0.00000000 |
| INODE             | 0.00000000 |
| SYSTEM            | 0.00000000 |
| UNKNOWN           | 0.00000000 |
| FILE_SPACE_HEADER | 0.00000000 |
| UNDO_LOG          | 0.00000000 |
| TRX_SYSTEM        | 0.00000000 |
| IBUF_BITMAP       | 0.00000000 |
+-------------------+------------+
9 rows in set (0.03 sec)

统计buffer pool里每个索引情况
select table_name as Table_Name,
       index_name as Index_Name,
       count(*) as Page_Count,
       sum(data_size)/1024/1024 as Size_in_MB
from information_schema.innodb_buffer_page
group by table_name, index_name
order by Size_in_MB desc;

[dba@localhost:mysql.sock] [(none)]> select table_name as Table_Name,
    ->        index_name as Index_Name,
    ->        count(*) as Page_Count,
    ->        sum(data_size)/1024/1024 as Size_in_MB
    -> from information_schema.innodb_buffer_page
    -> group by table_name, index_name
    -> order by Size_in_MB desc;
+----------------------------------------+-----------------------+------------+------------+
| Table_Name                             | Index_Name            | Page_Count | Size_in_MB |
+----------------------------------------+-----------------------+------------+------------+
| `SYS_TABLES`                           | CLUST_IND             |        102 | 1.42480850 |
| `SYS_COLUMNS`                          | CLUST_IND             |          3 | 0.02044487 |
| `mysql`.`innodb_index_stats`           | PRIMARY               |          3 | 0.01853943 |
| `sakila`.`city`                        | PRIMARY               |          2 | 0.01307106 |
| `sakila`.`customer`                    | PRIMARY               |          2 | 0.01018715 |
| `sakila`.`address`                     | PRIMARY               |          2 | 0.00889492 |
| `student`.`student`                    | PRIMARY               |          1 | 0.00844097 |
| `student`.`achievement`                | PRIMARY               |          1 | 0.00768566 |
| `sakila`.`actor`                       | PRIMARY               |          1 | 0.00715923 |
| `SYS_INDEXES`                          | CLUST_IND             |          1 | 0.00706387 |
| `SYS_FIELDS`                           | CLUST_IND             |          1 | 0.00527191 |
| `sakila`.`rental`                      | PRIMARY               |          2 | 0.00480556 |
| `sakila`.`film`                        | PRIMARY               |          2 | 0.00367451 |
| `sakila`.`country`                     | PRIMARY               |          1 | 0.00352764 |
| `sakila`.`payment`                     | PRIMARY               |          2 | 0.00313568 |
| `SYS_DATAFILES`                        | SYS_DATAFILES_SPACE   |          1 | 0.00310993 |
| `SYS_TABLESPACES`                      | SYS_TABLESPACES_SPACE |          1 | 0.00305367 |
| `world`.`city`                         | PRIMARY               |          2 | 0.00262070 |
| `SYS_TABLES`                           | ID_IND                |          1 | 0.00226593 |
| `SYS_FOREIGN`                          | ID_IND                |          1 | 0.00185108 |
| `mysql`.`innodb_table_stats`           | PRIMARY               |          1 | 0.00170231 |
| `SYS_FOREIGN_COLS`                     | ID_IND                |          1 | 0.00165081 |
| `sakila`.`inventory`                   | PRIMARY               |          2 | 0.00123596 |
| `SYS_FOREIGN`                          | FOR_IND               |          1 | 0.00107098 |
| `SYS_FOREIGN`                          | REF_IND               |          1 | 0.00104332 |
| `student`.`course`                     | PRIMARY               |          1 | 0.00090599 |
| `student`.`lecturer`                   | PRIMARY               |          1 | 0.00079823 |
| `sakila`.`category`                    | PRIMARY               |          1 | 0.00046444 |
| `dba`.`bank_card`                      | PRIMARY               |          1 | 0.00043392 |
| `dba`.`t1`                             | PRIMARY               |          1 | 0.00028992 |
| `app01`.`t1`                           | PRIMARY               |          1 | 0.00028229 |
| `mysql`.`server_cost`                  | PRIMARY               |          1 | 0.00026608 |
| `sakila`.`language`                    | PRIMARY               |          1 | 0.00025177 |
| `sakila`.`FTS_0000000000000042_CONFIG` | FTS_COMMON_TABLE_IND  |          1 | 0.00022221 |
| `sakila`.`staff`                       | PRIMARY               |          1 | 0.00020218 |
| `mysql`.`engine_cost`                  | PRIMARY               |          1 | 0.00010681 |
| `mysql`.`gtid_executed`                | PRIMARY               |          1 | 0.00006771 |
| `sakila`.`store`                       | PRIMARY               |          1 | 0.00004959 |
| `mysql`.`plugin`                       | PRIMARY               |          1 | 0.00003719 |
| `mysql`.`slave_worker_info`            | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`time_zone_transition`         | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`time_zone_transition_type`    | PRIMARY               |          1 | 0.00000000 |
| `SYS_VIRTUAL`                          | BASE_IDX              |          1 | 0.00000000 |
| `mysql`.`servers`                      | PRIMARY               |          1 | 0.00000000 |
| `query_rewrite`.`rewrite_rules`        | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`time_zone_leap_second`        | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`slave_relay_log_info`         | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`time_zone_name`               | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`slave_master_info`            | PRIMARY               |          1 | 0.00000000 |
| `mysql`.`time_zone`                    | PRIMARY               |          1 | 0.00000000 |
| NULL                                   | NULL                  |       6237 | 0.00000000 |
+----------------------------------------+-----------------------+------------+------------+
51 rows in set (0.02 sec)


内存管理
    IBP(innodb buffer pool)一般最高设置物理内存的50%-70%,实际使用值还会上浮约10%-15%。
    IBP是innodb_buffer_pool_chunk_size(默认128MB)的整数倍。
    从5.7开始,可以在线动态调整IBP,因此不建议一开始就设置过大。
    设置过大还有可能会导致swap问题。
    使用多个instance降低并发内存争用。(前提是buffer pool设置必须超过1G)
    page采用hash算法分配到多个instance中读写。
    每个缓冲区池管理其自己的数据。
        选项innodb_buffer_pool_instances不可动态调整。
        每个instance管理自己的free list、flush list、LRU list及其他,并由各自的buffer pool mutex负责并发控制。
[dba@localhost:mysql.sock] [(none)]> show engine innodb status\G
free list  => Free buffers
LRU list   => Database pages
flush list => Modified db pages

多少内存建议分配几个instance?
    总内存数/instances ≈ 8G-16GB

IBP动态resize
    MySQL 5.7版本新特性连载(四)http://t.cn/Ew1T6Nm
加大buffer pool
    以chunk_size为单位,分配新的内存pages。
    扩展AHI(adaptive hash index)链表,将新分配的pages包含进来。
    将新分配的pages添加到free list中。
缩减buffer pool
    重整buffer pool,准备回收pages(等待这些page里的脏页刷新完毕)。
    以chunk_size为单位,释放删除这些pages(这个过程会有一点点耗时)。
    调整AHI链表,使用新的内存地址。


latch
    latch作用
        内存锁,在内存中保护list的内存锁结构。
    两种latch
        mutex:lock_sys/trx_sys/log_sys,X,串行访问。
        rw-lock:S、X、SX,类似行锁的并行访问(读写互斥、读读并行)。
    想要获得latch(rounds),需要先spin wait(spins),如果获取不到会进入sleep状态(OS waits)。
    innodb_spin_wait_delay,两次spin wait之间的随机等待时间。设置为0可禁止等待间隙。
    热门mutex加log_sys->mutex,fil_system->mutex。
    查看当前latch争用情况
        [dba@localhost:mysql.sock] [(none)]> show engine innodb mutex;
        +--------+------------------------+---------+
        | Type   | Name                   | Status  |
        +--------+------------------------+---------+
        | InnoDB | rwlock: log0log.cc:846 | waits=2 |
        +--------+------------------------+---------+
        1 row in set (0.00 sec)
    
如何降低latch?
    优化、提高SQL效率,减少持有latch的数量。
    事务尽快结束,缩短持有latch时长。
    适当调高IBP instances,缩短latch list长度,降低搜索开销。


buffer pool预加载&导出
    innodb_buffer_pool_load_now
    innodb_buffer_pool_load_at_startup
    ------------------------------------
    innodb_buffer_pool_dump_pct
    innodb_buffer_pool_filename
    innodb_buffer_pool_dump_now
    innodb_buffer_pool_dump_at_shutdown

预读
    随机预读
        同一个extent里有13个热点page,就预读整个extent。
        yound list的前1/4算热点数据。
        innodb_random_read_ahead
    线性预读
        一个extent中有连续56个page都被顺序访问,则预读下一个extent。
        innodb_read_ahead_threshold

设置buffer pool刷新机制
    innodb_flush_method = O_DIRECT
预写
    脏页刷盘前检查相邻页是否也是脏页,一起刷盘。
    SSD设备上通常关闭,没必要采用预写。
    SSD设备上建议禁用innodb_flush_neighbors。

8.0的新变化
开始拆分buffer pool mutex(Percona贡献的patch)。
以往是有个全局的buffer pool mutext保护。
现在拆分到各个不同链表中,分为:
    LRU_list_mutex for the LRU_list
    zip_free mutex for the zip_free arrays
    zip_hash mutex for the zip_hash hash and in_zip_hash flag
    free_list_mutex for the free_list and withdraw list
    flush_state_mutex for init_flush, n_flush, no_flush arrays
redo log system采用lock-free机制,redo log checkpoint不再是顺序的,可能是在某个日志的中间,给崩溃恢复带来了一定的复杂度(需要回溯日志)
新增选项innodb_fsync_threshold,在创建或truncate文件之类的操作时调用,表示每写到这么多个字节时,要fsync一次,避免对系统产生冲击。

猜你喜欢

转载自www.cnblogs.com/zhouwanchun/p/12721888.html