逻辑存储结构-内存结构
表空间:ibd文件,一个mysql实例可以对应多个表空间,用于存储记录、索引等数据
段:分为数据段、索引段、回滚段,Innodb是索引组织表,数据段就是B+树的叶子节点,索引段即为B+树的非叶子节点。段用来管理多个Extent(区)。
区:表空间的单元结构,每个区的大小为1M。默认情况下,InnoDB存储引擎页大小为16K,即一个区中一共有64个连续的页。
页:是InnoDB存储引擎磁盘管理的最小单元,每个页的大小默认16KB。为了保证页的连续性,InnoDB存储默认从磁盘申请4-5个区。
行:InnoDB存储引擎数据是按行进行存放的。
buffer pool:缓冲池是主内存中的一个区域,里面可以缓存磁盘上经常操作的真实数据,在执行增删改查时,先操作缓冲池中的数据(若缓冲池没有数据,则从磁盘加载并缓存),然后再以一定频率刷新到磁盘;从而减少磁盘IO,加快处理速度。
缓冲池以page页为单位,底层采用链表数据结构管理page。根据状态,将page分为三种类型:
free page:空闲page,未被使用。
clean page:被使用page,数据没有被修改过。
dirty page:脏页,被使用page,数据被修改过,页中数据与磁盘的数据产生了不一致。
Change Buffer:更改缓冲区(针对于非唯一二级索引页),在执行DML语句时,如果这些数据page 没有在Buffer Pool中,不会直接操作磁盘,而会将数据变更存在更改缓冲区change buffer中,在未来数据被读取时,再将数据合并恢复到buffer pool中,再将合并后的数据刷新到磁盘中。
与聚集索引不同,二级索引通常是非唯一的,并且以相对随机的顺序插入二级索引。同样删除和更新可能会影响索引数据中不相邻的二级索引页,如果每一次都操作磁盘,会造成大量的磁盘IO。有了change buffer后,我们可以在缓冲池中进行合并处理,减少磁盘IO。
Adaptive Hash index:自适应hash索引,用于优化对buffer pool数据看查询。Innodb存储引擎会监控对表上各索引页的查询,如果观察到hash索引可以提升速度,则建立hash索引,称之为自适应hash索引。无需人工干预,是系统根据情况自动完成。
参数:adaptive_hash_index
mysql> show variables like '%hash%';
+----------------------------------+-------+
| Variable_name | Value |
+----------------------------------+-------+
| innodb_adaptive_hash_index | ON |
| innodb_adaptive_hash_index_parts | 8 |
| metadata_locks_hash_instances | 8 |
+----------------------------------+-------+
3 rows in set (0.00 sec)
Log Buffer:日志缓冲区,用来保存要写入到磁盘中的log日志数据(redo log、undo log),默认大小为16MB,日志缓冲区的日志会定期刷新到磁盘中。如果需要更新、插入或删除许多行的事务,增加日志缓冲区的大小可以节省磁盘IO.
参数:
innodb_log_buffer_size : 缓冲区大小
innodb_flush_log_at_trx_commit:日志刷新到磁盘时机
(1)完全符合 ACID 需要默认设置 1。每次事务提交时都会将日志写入并刷新到磁盘。写入最慢,最大安全性。
(2)设置为 0 时,每秒将日志写入并刷新到磁盘一次。写入速度最快,未刷新日志的事务可能会在崩溃中丢失。
(3)设置为 2 时,日志会在每次事务提交后写入,并每秒刷新到磁盘一次。写入速度较快,未刷新日志的事务可能会在崩溃中丢失。
设置0和2都不能 100% 保证每秒一次的刷新。由于大量 DDL 导致日志刷新可能会频繁地发生,有时由于调度问题,刷新可能也会不那么频繁。如果日志每秒刷新一次,则在崩溃中最多可能会丢失一秒的事务。如果日志刷新频率高于或低于每秒一次,则可能丢失的事务量也会相应变化。
MySQL提供一个sync_binlog参数来控制数据库的binlog刷到磁盘上去。
(1)sync_binlog=0,默认设置,表示每 sync_binlog 次事务提交后,MySQL 调用文件系统的刷新操作将缓存刷下去,这时候的性能是最好的,但是风险也是最大的。因为一旦系统 Crash,在 binlog_cache 中的所有 binlog 信息都会被丢失。
(2)sync_binlog=1,最安全的设置,表示每次事务提交,MySQL 都会把 binlog 刷下去,是最安全但是性能损耗最大的设置。这样的话,在数据库所在的主机操作系统损坏或者突然掉电的情况下,系统才有可能丢失 1 个事务的数据。但是binlog 虽然是顺序 IO,但是设置 sync_binlog=1,多个事务同时提交,同样也非常的影响 MySQL 和 IO 性能。虽然可以通过 group commit 的补丁缓解,但是刷新的频率过高对 IO 的影响也非常大。对于高并发事务的系统来说,“ sync_binlog ”设置为0和设置为1的系统写入性能差距可能高达5倍甚至更多。
(3)sync_binlog=n,当每进行n次事务提交之后,MySQL 将进行一次fsync之类的磁盘同步指令来将 binlog_cache 中的数据强制写入磁盘。
当两个参数设置为双1的时候,写入性能最差,sync_binlog=N (N>1 ), innodb_flush_log_at_trx_commit=2 时,MySQL 的写操作性能最好。
逻辑存储结构-磁盘结构
system Tablespace:系统表空间是更改缓冲区的存储区域。如果表是在系统表空间而不是每个表文件或通用表空间中创建的,他也可能包含表和索引数据。
参数:innodb_data_file_path
File-Per-Table Tablespaces:每个表的文件表空间包含单个InnoDB表的数据和索引,并存储在文件系统上的单个数据文件中。
参数:innodb_file_per_table
默认-每个表一个独立表空间
General Tablespaces:通用表空间,需要通过CREATE TABLESPACE 语法创建通用表空间,在创建表时,可以指定该表空间。
create tablespace xxxx add datafile ‘file_name’ ENGINE=engine_name;
create table ‘name’ engine=innodb tablespace='file_name';
mysql> create tablespace tshs1 add datafile 'tshs1.ibd' engine = innodb ;
Query OK, 0 rows affected (0.01 sec)
mysql> create table tb1(id int primary key auto_increment) tablespace = tshs1;
Query OK, 0 rows affected (0.01 sec)
Undo Tablespace :撤销表空间,MySQL 实例在初始化时会自动创建两个默认的undo表空间(初始化大小16M),用于存储undo log 日志。
undo001 undo002
Temporary Tablespaces:InnoDB 使用会话临时表空间和全局临时表空间,存储用户创建的临时表等数据
Doublewrite Buffer Files:双写缓冲区,Innodb引擎将数据页从Buffer Pool 刷新磁盘前,先将数据页写入双写缓冲区文件中,便于系统异常时恢复数据
ib_16384_0.dblwr
ib_16384_1.dblwr
Redo log: 重做日志,是用来实现事务的持久性。该日志文件由两部分组成:重做日志缓存(redo log buffer)以及重做日志文件(redo log),前者是在内存中,后者是在磁盘中,当事务提交之后会把所有修改信息都会存到该日志中,用于在刷新脏页到磁盘时,发生错误时,进行数据恢复使用
以循环的方式写入重做日志文件,涉及两个文件:ib_logfile0 , ib_logfile1
后台进程
Master Thread
核心后台线程,负载调度其他线程,还负责将缓冲池中的数据异步刷新磁盘中,保持数据的一致性。还包括脏页的刷新,合并插入缓存,undo页的回收。
IO Thread
在Innodb存储引擎中大量使用了AIO 来处理IO请求,这样可以极大的提高数据库性能,而IO Thread 主要负责这些IO 请求的回调。
mysql> show engine innodb status \G
*************************** 1. row ***************************
Type: InnoDB
Name:
Status:
=====================================
2023-07-17 10:11:35 0x7fbc864f8700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 30 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 4 srv_active, 0 srv_shutdown, 2935513 srv_idle
srv_master_thread log flush and writes: 2935517
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 7
OS WAIT ARRAY INFO: signal count 7
RW-shared spins 0, rounds 14, OS waits 6
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 14.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 47378
Purge done for trx's n:o < 0 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421923010664272, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (read thread)
I/O thread 7 state: waiting for completed aio requests (read thread)
I/O thread 8 state: waiting for completed aio requests (read thread)
I/O thread 9 state: waiting for completed aio requests (read thread)
I/O thread 10 state: waiting for completed aio requests (write thread)
I/O thread 11 state: waiting for completed aio requests (write thread)
I/O thread 12 state: waiting for completed aio requests (write thread)
I/O thread 13 state: waiting for completed aio requests (write thread)
I/O thread 14 state: waiting for completed aio requests (write thread)
I/O thread 15 state: waiting for completed aio requests (write thread)
I/O thread 16 state: waiting for completed aio requests (write thread)
I/O thread 17 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0, 0, 0, 0, 0] , aio writes: [0, 0, 0, 0, 0, 0, 0, 0] ,
ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
1512 OS file reads, 107 OS file writes, 43 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
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
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
Hash table size 69239, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 42314333
Log flushed up to 42314333
Pages flushed up to 42314333
Last checkpoint at 42314324
0 pending log flushes, 0 pending chkp writes
30 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 274857984
Dictionary memory allocated 164502
Buffer pool size 16382
Free buffers 14864
Database pages 1518
Old database pages 578
Modified db pages 0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 1478, created 40, written 62
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 1518, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=7421, Main thread ID=140447418664704, state: sleeping
Number of rows inserted 0, updated 0, deleted 0, read 4074989
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================1 row in set (0.00 sec)
Purge Thread
主要用于回收事务已经提交了的undo log,在事务提交之后,undo log可能不用了,就用它来回收
Page Clearner Thread
协助master Thread 刷新脏页到磁盘的线程,它可以减轻Master Thread 的工作压力,减少阻塞