Mysql认识Mysql重要架构

Posted new hilbert()

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mysql认识Mysql重要架构相关的知识,希望对你有一定的参考价值。

1.mysql 体系架构


MySQL Server架构自顶向下大致可以分网络连接层核心服务层存储引擎层系统文件层

网络连接层:

主要负责连接处理、身份验证、安全性等,一般 C/S 架构都会有这一层。

  • 客户端连接池:
    多个线程都会去获取一个数据库连接来访问数据库。不能每次都创建一个新的数据库连接,用完然后销毁,这样效率非常低下,因此客户端需要一个数据库连接池,每次从连接池里拿一个连接来处理SQL请求,用完之后又放回连接池中,避免频繁创建销毁数据库连接。

常见的数据库连接池有 DBCP、C3P0、Druid 等

  • mysql 连接器:
    客户端请求连接数据库时,连接器就会负责跟客户端建立连接、获取权限、维持和管理连接。MySQL服务器端也会有一个连接池,因为一般都会有多个系统与MySQL建立很多个连接,MySQL通过这个连接池去维护与客户端的数据库连接。

连接完成后,如果没有后续的动作,这个连接就处于空闲状态。客户端如果太长时间没动静,连接器就会自动将它断开。这个时间是由参数
wait_timeout 控制的,默认值是 8 小时

核心服务层:

MySQL 的核心服务都是在这层实现的。主要包含权限判断、查询缓存、解析器、查询优化器、缓存和执行计划。

  1. 权限判断可以审核用户有没有访问某个库、某个表,或者表里某行数据的权限。
  2. 缓存通过 Query Cache进行操作,如果数据在Query Cache 中,则直接返回结果给客户端,不必再进行查询解析、优化和执行等过程。
  3. 解析器针对 SQL语句进行解析,判断语法是否正确。
  4. 优化器对 SQL 进行改写和相应的优化,并生成最优的执行计划,就可以调用程序的 API接口,通过存储引擎层访问数据。

存储引擎层:

MySQL 数据库区别于其他数据库的最重要的一个特点就是其插件式的表存储引擎,存储引擎是底层物理结构的实现,负责数据的存储和提取。每个存储引擎都有各自的特点,可以根据具体的应用建立不同存储引擎表。

常用的存储引擎有 InnoDB、MyISAM、Memory 等,最常用的存储引擎是 InnoDB,它从 MySQL 5.5.8 版本开始成为默认的存储引擎。

系统文件层:

系统文件存储层主要是负责将数据库的数据和日志存储在系统的文件中,同时完成与存储引擎的之间的交互,是文件的物理存储层。

主要的一些文件有:数据文件、日志文件、配置文件等

可以使用 SHOW VARIABLES LIKE ‘%datadir%’; 命令查看数据文件的目录,在数据文件目录下我们可以看到如下的一些文件。


查看mysql日志信息,使用show variables like ‘log_%’ 命令

  • 数据存储文件

MySQL 数据库会在data目录下面建立一个以数据库为名的文件夹,用来存储数据库中的表文件数据。不同 的数据库引擎,每个表的扩展名也不一样

  1. .frm:8.0之前无论是那种存储引擎,创建表之后就一定会生成一个以表明命名的’.frm’文件。frm文件主要存放与表相关的数据信息,主要包括表结构的定义信息。当数据库崩溃时,用户可以通过frm文件来恢复数据表结构。
  2. InnoDB数据文件:

.ibd:使用独享表空间存储表数据和索引信息,一张表对应一个ibd文件
.ibdata:使用共享表空间存储表数据和索引信息,所有表共同使用一个或者多个ibdata文件

共享表空间: 某一个数据库的所有的表数据,索引文件全部放在一个文件中。
独占表空间: 每一个表都将会生成以独立的文件方式来进行存储,每一个表都有一个.frm表描述文件,还有 一个.ibd文件。其中这个文件包括了 单独一个表的数据 内容以及索引内容。

show variables like "innodb_file_per_table"; 
ON代表独立表空间管理,OFF代表共享表空间管理

共享表空间:
优点: 
	1.可以放表空间分成多个文件存放到各个磁盘上。数据和文件放在一起方便管理。

缺点: 
	1.所有的数据和索引存放到一个文件中,多个表及索引在表空间中混合存储,这样对于一个表做了大量删除操作后表空间中将会有大量的空隙。

独立表空间:
优点:
	1.每个表都有自已独立的表空间。
	2.每个表的数据和索引都会存在自已的表空间中。
	3.可以实现单表在不同的数据库中移动。 
	4.空间可回收(Drop table 操作自动回收表空间)

缺点:
	1.单表增加过大,如超过100 G
  1. MyISAM数据文件:

.MYD:主要用来存储表数据信息
.MYI:主要用来存储表数据文件中任务索引的数据树

MySQL8.0中不再单独提供b.frm,而是合并在b.ibd文件中

到存储ibd文件的目录下,执行下面的命令:

shell ibd2sdi --dump-file=解析后的文件名.txt 要解析的表名.ibd


  • 日志文件

常用的日志包括:错误日志、二进制日志、查询日志、慢查询日志等等

  1. 错误日志
    错误日志(Error Log)是 MySQL 中最常用的一种日志,主要记录 MySQL 服务器启动和停止过程中的信 息、服务器在运行过程中发生的故障和异常情况等
# 查看错误日志记录位置
show variables like "log_error";
# 在 MySQL 中,可以使用 mysqladmin 命令来开启新的错误日志,以保证 MySQL 服务器上的硬盘空间。
# mysqladmin 命令的语法如下:
mysqladmin -uroot -p flush-logs
# 执行该命令后,MySQL 服务器首先会自动创建一个新的错误日志,然后将旧的错误日志更名为 filename.err-old 。可以手动直接删除。

#配置文件中配置
[mysqld]
log-error=dir/filename
  1. 二进制日志(binlog)
    二进制日志 binlog 用于记录数据库执行的写入性操作(不包括查询)信息,以二进制的形式保存在磁盘中。使用任何存储引擎的 mysql 数据库都会记录 binlog 日志。在 binlog 中记录的是逻辑日志,也就是 SQL 语句。SQL 语句执行后,binlog 追加到日志文件中。可以设置 binlog 文件大小,超过大小后,自动创建新的文件。

binlog 有三种格式,分别为 STATMENT、ROW 和 MIXED

  • STATMENT:把会修改数据的 sql 语句记录到 binlog 中;是 MySQL 5.7.7 之前的默认格式;
  • ROW:不记录每条 sql 语句的上下文信息,仅记录哪条数据被修改了;是 MySQL 5.7.7之后的默认格式;
  • MIXED:基于 STATMENT 和ROW 两种模式的混合复制,一般使用 STATEMENT 模式,对于无法复制的操作使用 ROW 模式;
show variables like 'log_bin%'

mysql-index.0000XX : 保存着对MySQL更改的逻辑
mysql-index.index : 就是位置索引,后续备份恢复使用

show binlog events in 'mysql-bin.000049'; #查看指定binlog文件的内容 

  1. 查询日志
    查询日志在mysql中被称之为 general log(通用日志),不要被"查询日志"的名字误导,查询日志不只是记录select语句,查询日志记录了数据库执行的命令,不管这些语句是否正确,都会被记录。
show VARIABLES LIKE 'general_log';
将查询日志存放于 mysql.general_log 表中
general_log:表示查询日志是否开启,ON表示开启,OFF表示未开启,默认为OFF
  1. 慢日志
    所谓的慢查询就是通过设置来记录超过一定时间的SQL语句
    开启MySQL的慢查询日志功能
# 查看是否开启 未使用索引的SQL记录日志查询
show variables like 'log_queries_not_using_indexes';
# 开启 未使用索引的SQL记录日志查询
set global log_queries_not_using_indexs=on/off;
# 查看超过多长时间的查询记入慢查询日志中
show variables like 'long_query_time';
# 设置记录时长,0为全部记录,设置之后需重新启动
set global long_query_time=10
# 查看是否开启 mysql慢查询日志功能
show variables like 'slow_qurey_log'
# 开启、关闭慢日志
set global slow_qurey_log=on/off;
# 查看日志记录位置
show variables like 'slow_query_log_file';
#日志存储方式
show variables like "log_output";
  • 配置文件
    用于存放MySQL所有的配置信息的文件,比如:my.cnf、my.ini
### 查找配置文件
/usr/local/mysql/bin/mysqld --verbose --help |grep -A 1 'Default options'

### 查找结果
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf ~/.my.cnf 

2.Innodb 架构图


Innodb 内存布局

(1) Buffer Pool

Buffer Pool是MYSQL数据库中的一个重要的内存组件,介于外部系统和存储引擎之间的一个缓存区,针数据库的增删改查这些操作都是针对这个内存数据结构中的缓存数据执行的,在操作数据之前,都会将数据从磁盘加载到Buffer Pool中,操作完成之后异步刷盘、写undo log、binlog、redolog等一些列操作,避免每次访问都进行磁盘IO影响性能

MySQL服务器启动的时候就会向操作系统申请一片连续的内存,即 Buffer Pool。默认配置下 Buffer Pool 只有128MB 大小,我们可以调整 innodb_buffer_pool_size 参数来设置 Buffer Pool 的大小

为了管理 Buffer Pool 中的缓存页,InnoDB 为每一个缓存页都创建了一些描述信息(元数据),用来描述这个缓存页。描述信息主要包括该页所属的表空间编号、页号、缓存页的地址、链表节点信息、锁信息、LSN信息等等

这个描述信息本身也是一块数据,它们占用的内存大小都是相同的。在 Buffer Pool 中,每个缓存页的描述信息放在最前面,各个缓存页在后面。看起来就像下图这个样子。

每个描述数据大约相当于缓存页大小的 5%,也就是800字节左右的样子。而我们设置的 innodb_buffer_pool_size 并不包含描述数据的大小,实际上 Buffer Pool 的大小会超出这个值。 比如默认配置 128MB,那么InnoDB在为 Buffer Pool 申请连续的内存空间时,会申请差不多 128 + 128*5% ≈ 134MB 大小的空间


InnoDB 并不是一次性申请 pool_size 大小的内存空间,而是以 chunk 为单位申请。一个 chunk 默认就是 128M,代表一片连续的空间,申请到这片内存空间后,就会被分为若干缓存页与其对应的描述信息块。

也就是说一个Buffer Pool实例其实是由若干个chunk组成的,每个chunk里划分了描述信息块和缓存页,然后共用一套 Free链表、LRU链表、Flush链表。

需要注意的是,链表的基础节点占用的内存空间并不包含在 Buffer Pool 之内,而是单独申请的一块内存空间,每个基节点只占用40字节大小

重点: 描述信息有flush_pre ,flush_next ,free_pre, free_next 指针

  • Free 链表
    InnoDB 设计了一个 free 链表,它是一个双向链表数据结构,这个链表的每个节点就是一个空闲缓存页的描述信息。

每个描述信息中有 free_pre、free_next 两个指针,Free链表 就是由这两个指针连接起来形成的一个双向链表。然后Free链表 有一个基础节点,这个基础节点存放了链表的头节点地址、尾节点地址,以及当前链表中节点数的信息。

作用: 有了这个 Free链表 之后,当需要从磁盘加载一个页到 Buffer Pool 时,就从 Free链表 中取出一个描述数据块,然后将页写入这个描述数据块对应的空闲缓存页中。并把一些描述数据写入描述数据块中,比如页的表空间号、页号之类的。最后,把缓存页对应的描述数据块从 Free链表 中移除,表示该缓存页已被使用了。

  • LRU 链表
    因为缓冲池大小是有限的,不可能一直加载数据到缓冲池中,对于一些频繁访问的数据可以一直留在缓冲池中,而一些很少访问的数据,当缓存页快用完了的时候,就可以淘汰掉一些。这时就可以使用 LRU链表 来管理已使用的缓存页,这样就可以知道哪些页最常使用,哪些页最少使用了。(最近使用的放到了头部,不怎么使用的到了尾部去)

存在问题:
1、InnoDB 有一个预读机制,就是从磁盘上加载一个数据页的时候,可能连带着把这个数据页相邻的其它数据页都加载到缓存里去。虽然预读了其它页,但可能都没用上,但是这些页如果都往 LRU 头部放,就会导致原本经常访问的页往后移,然后被淘汰掉。这种情况属于加载到 Buffer Pool 中的页不一定被用到导致缓存命中率降低。

2、如果我们写了一个全表扫描的查询语句,一下就将整个表的页加载到了 LRU 的头部,如果表记录很多的话,可能 LRU 链表中之前经常被访问的页一下就淘汰了很多,而留下来的数据可能并不会被经常访问到。这种就是加载了大量使用频率很低的页到 Buffer Pool,然后淘汰掉使用频率很高的页,从而导致缓存命中率降低

为了解决简单 LRU 链表的问题,InnoDB在设计 LRU 链表的时候,实际上是采取冷热数据分离的思想,LRU链表会被拆成两部分,一部分是热数据(又称new列表),一部分是冷数据(又称old列表)

1.LRU链表分为冷、热数据区域,前 63% 为热数据区域,后 37% 为冷数据区域,加载缓存页先放到冷数据区域头部。
2.冷数据区域的缓存页第一次访问超过1秒后,再次访问时才会被移动到热数据区域头部。
3.热数据区域中,只有后 3/4的缓存页被访问才会移到头部,前 1/4 被访问到不会移动。
4.淘汰数据优先淘汰冷数据区域尾部的缓存页。

  • Flush 链表
    定位哪些数据页是脏页,需要将脏页数据刷回磁盘中。Flush链表 跟前面两个链表一样,也有一个基础节点,如果一个缓存页被修改了,就会加入到 Flush链表中。

描述信息块中还有两个指针 flush_pre、flush_next用来连接形成 flush 链表,所以 Flush链表 中的缓存页一定是在 LRU 链表中的,而 LRU 链表中不在 Flush链表 中的缓存页就是未修改过的页

(2) change buffer

当需要更新一个数据页时,如果数据页在内存中就直接更新,而如果这个数据页还没有在内存中的话,在不影响数据一致性的前提下,InooDB会将这些更新操作缓存在change buffer中,这样就不需要从磁盘中读入这个数据页了。

在下次查询需要访问这个数据页的时候,将数据页读入内存,然后执行change buffer中与这个页有关的操作。通过这种方式就能保证这个数据逻辑的正确性

将change buffer中的操作应用到原数据页,得到最新结果的过程称为merge。除了访问这个数据页会触发merge外,系统有后台线程会定期merge。在数据库正常关闭(shutdown)的过程中,也会执行merge操作。

什么条件下能用Change buffer?

对于唯一索引来说,所有的更新操作都要先判断这个操作是否违反唯一性约束。比如,要插入id =5这个记录,就要先判断现在表中是否已经存在id=5的记录,而这必须要将数据页读入内存才能判断。那都读到内存了,就没有必要用change buffer,change buffer 目的是为了减少磁盘IO次数

因此,唯一索引的更新就不能使用change buffer,实际上也只有普通索引可以使用。

redo log 节省的是随机写磁盘的 IO 消耗(虽然也是磁盘,但是转成顺序写日志)
change buffer要节省随机读磁盘的 IO 消耗。如果没有它, 要先把数据从磁盘读入内存, 再在内存改, 有他省了一步

那么在什么场景下会触发ChangeBuffer的Merge操作呢?

  1. 访问变更操作对应的数据页;
  2. InnoDB后台定期Merge;
  3. 数据库BufferPool空间不足;
  4. 数据库正常关闭时;
  5. RedoLog写满时;

问题:change buffer 记录了一个delete 操作,例如 delete from table where x = a ,但是此时insert 一条带有主键的语句咋办?(刚好这个主键是在条件等于x=a的范围之内 )

插入主键的时候,用不到change buffer ,需要将磁盘页面加载的buffer pool ,这个时候change buffer的数据会修改对应的页,将这个范围的记录的is_delete设置成1,是可以插入成功的,不会报主键冲突。

(3) Adaptive Hash Index 自适应hash索引

InnoDB存储引擎会监控对表上各索引页的查询。并建立合适的哈希索引,加速数据页的访问

特点

  • 哈希索引,查询消耗 O(1)
  • 降低对二级索引树的频繁访问资源。
  • 自适应

缺点

  • hash自适应索引会占用innodb buffer pool;
  • 自适应hash索引只适合搜索等值的查询,如select * from table where index_col=‘xxx’,而对于其他查找类型,如范围查找,是不能使用的;

Innodb存储引擎会监控对表上二级索引的查找,如果发现某二级索引被频繁访问,innodb就会使用索引键的前缀建立一个哈希索引。将索引值转换为一种指针,便于直接访问,带来速度的提升。
经常访问的二级索引数据会自动被生成到hash索引里面去(最近连续被访问三次的数据)

(4) log buffer

InnoDB redo log是存储引擎的WAL日志,用于数据库的crash recovery,保证在系统故障时数据库数据的可靠安全。用户事务在写redo log时并不是直接写入redo log file,而是先写到redo log buffer,再由后台的log_writer线程和log_flush线程负责写入file,以提升数据库的写入性能。

Innodb 磁盘布局

InnoDB 逻辑存储结构:
表空间可以看做是InnoDB存储引擎逻辑结构的最高层,所有的数据都存放在表空间中。

  1. 段(segment)
    段(Segment)分为索引段,数据段,回滚段等。其中索引段就是非叶子结点部分,而数据段就是叶子结点部分回滚段用于数据的回滚和多版本控制。一个段包含256个区(256M大小)
  2. 区(extent)
    区是页的集合,一个区包含64个连续的页,默认大小为 1MB (64*16K)
  3. 页(page)
    InnoDB 将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,也就是一次最少从磁盘中读取一页16KB的内容到内存中,一次最少把内存中的16KB内容刷新到磁盘中

File Header: 用来记录页的一些头信息,由8个部分组成,固定占用38字节
关键属性:FIL_PAGE_LSN 该值代表该页最后被修改的日志序列位置LSN(Log Sequence Number)

Page Header: 该部分用来记录数据页的状态信息,由14个部分组成,共占用56字节,如下表所示

Infimum和Supremum Record:
InnoDB 每个数据页中有两个虚拟的行记录,用来限定记录的边界。Infimum记录是比该页中任何主键值都要小的记录,Supremum记录 是比改页中何主键值都要大的记录。这两个记录在页创建时被建立,并且在任何情况下不会被删除。

User Record 和 Free Space

User Records就是实际存储行记录的部分,Free Space明显就是空闲空间

Free Space很明显指的就是空闲空间,同样也是个链表数据结构。在一条记录被删除后,设置delete_mask 为1, 然后该空间会被加入到空闲链表中,这部分空间就可以被利用起来。

Page Directory
Page Directory(页目录)中存放了记录的相对位置,页中的记录分为了多个组,槽就存放了每个组中最大的那条记录的相对位置(记录在页中的相对位置,不是偏移量),在 InnoDB中并不是每个记录拥有一个槽, InnoDB存储引擎的槽是一个稀疏目录(sparse directory),即一个槽中可能包含多个记录。

假设有(1,2,3,4,5,6,7,8,9,10)同时假设一个槽中包含4条记录,则 Slots中的记录可能是(1,5,8)

File Trailer
在将页写入磁盘时,最先写入的便是 File Header 中的 FIL_PAGE_SPACE_OR_CHKSUM 值,就是页面的校验和。在写入的过程中,数据库可能发生宕机,导致页没有完整的写入磁盘。

为了校验页是否完整写入磁盘,InnoDB 就设置了 File Trailer 部分。File Trailer 中只有一个FIL_PAGE_END_LSN,占用8字节。FIL_PAGE_END_LSN 又分为两个部分,前4字节代表页的校验和;后4字节代表页面被最后修改时对应的日志序列位置(LSN),与File Header中的FIL_PAGE_LSN相同。

  1. InnoDB行记录

目前,InnoDB支持4中行记录格式,分别是 Compact、Redundant、Dynamic和Compressed 行格式。

COMPACT 行记录格式

  • 变长字段长度列表
  1. MySQL中有一些变长字段类型,如 VARCHAR(M)、TEXT、BLOB 等,变长字段的长度是不固定的,所以在存储数据的时候要把这些数据占用的字节数也存起来,读取数据的时候才能根据这个长度列表去读取对应长度的数据。
  2. 变长字段长度列表 就是用来记录一行中所有变长字段的真实数据所占用的字节长度,并且各变长字段数据占用的字节数是按照列的顺序逆序存放
  3. 变长字段长度列表中只存储值为非NULL的列内容占用的长度,值为 NULL 的列的长度是不储存的
  • NULL值列表
    表中的某些列可能会存储NULL值,如果把这些NULL值都放到记录的真实数据中会比较浪费空间,所以Compact行格式把这些值为NULL的列存储到NULL值列表中。
二进制位的值为1时,代表该列的值为NULL。
二进制位的值为0时,代表该列的值不为NULL
  • 记录头信息
    记录头信息是由固定的5个字节组成,5个字节也就是40个二进制位
  • 记录真实数据
    每行数据除了用户定义的列外,在开头还有两个隐藏列,事务ID列(DB_TRX_ID)和回滚指针列(DB_ROLL_PTR),分别为6字节和7字节的大小。若InnoDB表没有定义主键,每行还会增加一个6字节的行ID列(DB_ROW_ID)

如果我们没有为某个表显式的定义主键,并且表中也没有定义唯一索引,那么InnoDB会自动为表添加一个row_id的隐藏列作为主键。

B+树结构如下:

(1) 系统表空间(共享表空间)

在默认情况下InnoDB存储引擎有一个共享表空间ibdata1(系统表空间 System TableSpaces)系统表空间可以有一个或多个数据文件。默认情况下, ibdata1在数据目录中创建一个名为 的系统表空间数据文件。系统表空间数据文件的大小和数量由innodb_data_file_path启动选项定义。

InnoDB系统表空间包含InnoDB数据字典(InnoDB相关对象的元数据),是doublewrite缓冲区,change buffer更改缓冲区和undo logs回滚日志的存储区域
系统表空间还包含任何用户在系统表空间中创建的表和索引数据。
系统表空间被视为共享表空间,因为它被多个表共享。


独享模式:通过innodb_file_per_table=ON 来开启,使用ibd文件来存放数据,且每个表一个ibd文件。

在独享表空间模式下,表数据page就不属于系统表空间了

共享模式:默认情况下是共享模式。使用ibdata文件,所有表共同使用一个(或者多个、自行配置)ibdata文件。

在共享模式下,表的数据page也是属于系统表空间的

  • 数据字典
    InnoDB数据字典由内部系统表组成。这些系统表包含用于跟踪对象(如表,索引和列)的元数据

有4个最基本的系统表来存储表的元数据:表、列、索引、索引列等信息。这4个表分别是SYS_TABLES、SYS_COLUMNS、SYS_INDEXES、SYS_FIELDS

  • double write
    (1)脏页刷盘风险 关于IO的最小单位:
      1、数据库IO的最小单位是16K(MySQL默认,oracle是8K)
      2、文件系统IO的最小单位是4K(也有1K的)
      3、磁盘IO的最小单位是512字节
    因此,存在IO写入导致page损坏的风险:

(2)两次写: (提高innodb的可靠性,用来解决部分写失败(partial page write页断裂))

为什么不能用redo log 恢复?
因为这时候落磁盘的页已经损坏了,redo log记录的是对页的物理修改,如果页本身已经损坏,redo log也无能为力

double write工作流程

doublewrite由两部分组成,一部分为内存中的doublewrite buffer,其大小为2MB,另一部分是磁盘上共享表空间(ibdata x)中连续的128个页,即2个区(extent),大小也是2M。


  1、当一系列机制触发数据缓冲池中的脏页刷新时,并不直接写入磁盘数据文件中,而是先拷贝至内存中的doublewrite buffer中;
  2、接着从两次写缓冲区分两次写入磁盘共享表空间中(连续存储,顺序写,性能很高),每次写1MB;
  3、待第二步完成后,再将doublewrite buffer中的脏页数据写入实际的各个表空间文件(离散写);(脏页数据固化后,即进行标记对应doublewrite数据可覆盖)

(3)doublewrite的崩溃恢复:
  如果操作系统在将页写入磁盘的过程中发生崩溃,在恢复过程中,innodb存储引擎可以从共享表空间的doublewrite中找到该页的一个最近的副本,将其复制到表空间文件,再应用redo log,就完成了恢复过程。

  • change buffer
    在磁盘上,更改缓冲区是system tablespace系统表空间的一部分,因此在数据库重新启动时,索引更改仍保存在缓存中。为了保证change buffer 持久化。
  • undo log 回滚日志
    回滚日志undo log 是与事务关联的undo log记录的集合。当我们对记录做了变更操作时就会产生undo记录,Undo记录默认被记录到系统表空间(ibdata)中,但从5.6开始,也可以使用独立的Undo 表空间。

Undo记录中存储的是老版本数据,当一个旧的事务需要读取数据时,为了能读取到老版本的数据,需要顺着undo链找到满足其可见性的记录。


InnoDB支持128个回滚段,每个段最多支持1023个并发数据修改事务,总共限制大约128K个并发数据修改事务(只读事务不计入最大限制)。每个事务都被分配到其中一个回滚段,并在该持续时间内与该回滚段保持关联。 innodb_rollback_segments选项定义了InnoDB使用的回滚段数

(2) undo tablespaces (独立的回滚表空间)

从5.6开始,可以使用独立的Undo 表空间,可以配置undo log存放在独立的undo tablespaces里面。配置单独的undo tablespaces时,系统表空间中的回滚段将失效。undo tablespaces由一个或多个回滚日志文件组成。

innodb_undo_tablespaces
定义使用的undo tablespaces数量,这个选项必须在初始化MySQL之前进行配置。
这个值也对应undo log文件的个数,每个undo log文件代表一个独立的回滚表空间。

innodb_undo_directory 
undo tablespaces文件的存放目录

innodb_rollback_segments
定义回滚段的总数量。innodb_rollback_segments的默认设置为128,这也是最大值

(3)file-per-table表空间(独立的数据表空间)

独立表空间:
优点:
	1.每个表都有自已独立的表空间。
	2.每个表的数据和索引都会存在自已的表空间中。
	3.可以实现单表在不同的数据库中移动。 
	4.空间可回收(Drop table 操作自动回收表空间)

File-per-table 表空间与共享表空间(如系统表空间或通用表空间)相比具有以下优点

  • 在截断或删除在 file-per-table表空间中创建的表后,磁盘空间将返回给操作系统。截断或删除存储在共享表空间中的表会在共享表空间数据文件中创建只能用于nnoDB数据的可用空间。换句话说,共享表空间数据文件在表被截断或删除后不会缩小
  • ALTER TABLE对位于共享表空间中的表执行表复制操作会增加表空间占用的磁盘空间量。此类操作可能需要与表中的数据加上索引一样多的额外空间。该空间不会像file-per-table 表空间那样释放回操作系统。
  • TRUNCATE TABLE在驻留在 file-per-table 表空间中的表上执行时性能更好。

(4)General Tablespaces(通用表空间)

与系统表空间类似,通用表空间是能够为多个表存储数据的共享表空间

通用表空间是使用 CREATE TABLESPACE 语法创建的

## 创建表空间
CREATE TABLESPACE tablespace_name
    ADD DATAFILE 'file_name'
    [FILE_BLOCK_SIZE = value]
        [ENGINE [=] engine_name]

## 将表添加到通用表空间
 CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_nameALTER TABLE tbl_name TABLESPACE [=] tablespace_name

(5)Temporary Tablespaces(临时表空间)

非压缩的、用户创建的临时表和磁盘内部临时表是在共享临时表空间中创建的

临时表空间在正常关闭或中止初始化时被删除,并在每次服务器启动时重新创建。临时表空间在创建时会收到一个动态生成的空间 ID。
如果无法创建临时表空间,则拒绝启动。如果服务器意外停止,则不会删除临时表空间。在这种情况下,数据库管理员可以手动删除临时表空间或重新启动服务器,服务器会自动删除并重新创建临时表空间

## 配置 innodb_temp_data_file_path 变量以指定最大文件大小
innodb_temp_data_file_path=ibtmp1:12M:autoextend:max:500M

参考文章:

大白话带你认识MySQL背后优秀的架构设计

前两天看到字节一个老哥写的帖子,提到高阶开发者必须掌握的技能,其中他明确提出了“精通MySQL”。

 

为啥MySQL对开发人员如此重要?

第一,不管你去面试哪家公司,数据库是必问项,而MySQL使用范围广,无论如何是避不开的;

第二,你对MySQL掌握的越深入,意味着你能做的事情越多。


实现业务功能,要懂基本的SQL语句;

性能优化,那么索引、引擎就要摸透;

想分库分表,主从同步机制、读写分离你就得了解;

安全方面,你得知道权限、备份、日志等等;

涉及到云数据库,就得懂源码及瓶颈。

 

我在面试的时候也经常看到一些程序员写“精通MySQL”,但大多数人对精通存在一定误区

 

由于业务需求,我们常常需要对MySQL进行优化,而优化并不总是对一个单纯环境进行,还可能是面对一个复杂的已投产系统。

 

对于大部分程序员来说,MySQL用了很久,但依然会出现面对棘手问题束手无策的状况,大多是因为对数据库出现问题的情况和处理思路模糊不清。

 

我入行前3年也会有这样的问题,看了很多大咖的分享。总结下来,任何一项技术的体系都是庞杂的,想要真正掌握,就需要摸透底层逻辑,这样才能以不变应万变。

 

前段时间和玄姐(前58集团技术主席孙玄)聊,收获颇多。他谈到,以架构师的思路和视野学习 MySQL ,既能够夯实分库分表、分布式部署等核心技术点,又能够掌握普通开发者,难以触及的 MySQL 架构设计方法论。你在数据库层面,在工作中、团队里、面试时,也就拥有了同行难以复制的核心竞争力。


为帮助更多开发工程师、架构师掌握 MySQL 核心,玄姐联手快狗打车CTO沈剑老师,结合10多年一线大厂实践经验,打磨了一套《3天挑战架构师级MySQL海量数据设计与实践 》在线专栏课。3天时间名师将带你深入学习架构师级 MySQL,掌握核心架构技术,并在千亿级企业真实海量数据案例中(电商、微信等),培养你的 MySQL 实战能力。


大白话带你认识MySQL背后优秀的架构设计
原价 ¥ 499 限时  ¥9.8 立刻学习!

大白话带你认识MySQL背后优秀的架构设计

以上是关于Mysql认识Mysql重要架构的主要内容,如果未能解决你的问题,请参考以下文章

MySql优化及基本架构

5分钟学会mysql的逻辑架构原理

MySQL认识索引

MySQL体系架构

打通MySQL架构和业务的任督二脉

做了这么久的 DBA,你真的认识 MySQL 数据安全体系?