InnoDB 的历史
年份 | 事件 | 备注 |
---|---|---|
1995 | 由 Heikki Tuuri 创建 Innobase Oy 公司,并开发 InnoDB 存储引擎 | Innobase 开始做的是数据库,希望卖掉该公司 |
1996 | MySQL 1.0 发布 | |
2000 | MySQL 3.23 版本发布 | |
2001 | InnoDB 存储引擎集成到 MySQL 数据库 | 作为插件的方式集成 |
2006 | Innobase 被 Oracle 公司收购(InnoDB 作为开源产品,性能和功能很强大) | InnoDB 在被收购后的,MySQL 中的 InnoDB 版本没有改变 |
2010 | MySQL 5.5 版本 InnoDB 存储引擎称为默认存储引擎 | MySQL 被 Sun 收购,Oracle 被 Oracle 收购,使得 MySQL 和 InnoDB 重新在一起配合开发 |
至今 | 其他存储引擎已经不再得到 Oracle 官方的后续开发 |
InnoDB 的特点
- Fully ACID:InnoDB 默认的 Repeat Read 隔离级别就支持
- Row-level Locking:支持行锁
- Multi-version concurrency control(MVCC):支持多版本并发控制
- Foreign key support:支持外键
- Automatic deadlock detection:死锁自动检测
- High performance、High scalability、High availability:高性能,高扩展,高可用
InnoDB 存储引擎的文件
概述
InnoDB 的文件主要分为两个部分,一个是表空间文件,一个是重做日志文件。
表空间文件
- 独立表空间文件
- 全局表空间文件
- Undo 表空间文件(from MySQL 5.6)
重做日志文件
- 物理逻辑日志
- 没有 Oracle 的归档重做日志
InnoDB 表空间
表空间的概念
- 表空间是一个逻辑存储的概念
- 表空间可以由多个文件组成
- 支持裸设备(可以直接使用 O_DIRECT 方式绕过缓存,直接写入磁盘)
表空间的分类
系统表空间 (最早只有系统表空间)
- 存储元数据信息
- 存储 Change Buffer 信息
- 存储 Undo 信息
- 一开始所有的表和索引的信息都是存储在系统表空间中,随后 InnoDB 对其做了改进,可以使用独立的表空间
独立表空间
- innodb-file-per-table=1(开启支持每个表一个独立的表空间)
- 每张用户表对应一个独立的 ibd 文件
- 分区表可以对应多个 ibd 文件
Undo 表空间
- MySQL 5.6 版本支持独立的 Undo 表空间
innodb_undo_tablespaces=3,创建3个 Undo 表空间
shell> ll undo*
-rw-r-----. 1 mysql mysql 7340032 Jan 3 17:21 undo001
-rw-r-----. 1 mysql mysql 7340032 Jan 3 17:40 undo002
-rw-r-----. 1 mysql mysql 7340032 Jan 3 17:21 undo003
临时表空间
MySQL 5.7 增加了临时表空间(ibtmp1)
- innodb_temp_data_file_path
查看 MySQL 的 datadir 目录。
shell> ll ib* # MySQL的datadir目录
-rw-r-----. 1 mysql mysql 22913 Dec 27 23:56 ib_buffer_pool
-rw-r-----. 1 mysql mysql 12582912 Jan 3 15:27 ibdata1 # 系统表空间,默认所有信息存在这里
-rw-r-----. 1 mysql mysql 134217728 Jan 3 15:27 ib_logfile0
-rw-r-----. 1 mysql mysql 134217728 Jan 3 15:27 ib_logfile1
-rw-r-----. 1 mysql mysql 12582912 Jan 3 15:27 ibtmp1 # 零时表空间
shell> cd burn_test # 在MySQL的datadir目录下,burn_test是自定义数据库,根据配置,默认为innodb的表
shell> ll test_1*
-rw-r-----. 1 mysql mysql 8554 Dec 3 20:14 test_1.frm # test_1表的表结构文件
# mysqlfrm --diagnostic test_1.frm可查看表结构
-rw-r-----. 1 mysql mysql 49152 Dec 3 20:14 test_1.ibd # ibd就是test_1这张表对应的innodb文件
# ibd中包含了索引和数据
- 同一个表空间(ibdata1)存储和独立表空间存储就性能上而言没有区别;
- 当需要删除表(drop table)时,独立的表空间存储可以直接删除文件,而 ibdata1 存储也只是把该部分表空间标记为可用,所以从速度上看很难说哪个更快;但是删除文件后,ibdata1 占用的空间不会释放;
- 分区表,每个分区会产生独立的 ibd 文件 ;
- 独立的表空间,一个表对应一个 ibd 文件,给人的感觉更加直观;
- 单个 ibd 文件直接拷贝到新的数据库中无法直接恢复:
innodb_log_file_size
- 该文件设置的尽可能的大,模板中给出的大小是 4G
- 设置太小可能会导致脏页刷新时夯住
General 表空间
General 表空间是 InnoDB 使用 CREATE TABLESPACE 语法创建的共享表空间。
官方文档:https://dev.mysql.com/doc/refman/5.7/en/general-tablespaces.html
假如,新建一张表并让该表的存储路径不是默认的路径 datadir/dbname,而是指定存储的位置,应该如何处理?
方法一:
shell> mkdir /GeneralTest
shell> chown mysql.mysql /GeneralTest
mysql> create table test_ger1 (a int) data directory='/GeneralTest';
Query OK, 0 rows affected (0.15 sec)
shell> cd /GeneralTest
shell> tree
.
└── burn_test # dbname
└── test_ger1.ibd # 表空间文件
1 directory, 1 file
shell> ll test_ger1* # 在datadir 的 burn_test 目录下
-rw-r-----. 1 mysql mysql 8554 Jan 3 16:41 test_ger1.frm
-rw-r-----. 1 mysql mysql 36 Jan 3 16:41 test_ger1.isl # 这是链接文件,链接到上面的ibd文件
shell> cat test_ger1.isl # 一个文本文件,内容就是idb文件的路径
/GeneralTest/burn_test/test_ger1.ibd
方法二:
-- 使用`通用表空间`
-- 1: 创建一个通用表空间
mysql> create tablespace ger_space add datafile '/GeneralTest/ger_space.ibd' file_block_size=8192;
Query OK, 0 rows affected (0.07 sec)
-- datafile 指定存储路径后,在datadir下会产生一个isl文件,该文件的内容为General space的ibd文件的路径
-- 如果datafile不指定路径,则ibd文件默认存储在datadir目录下,且不需要isl文件了
mysql> create tablespace ger2_space add datafile 'ger2_space.ibd' file_block_size=8192;
Query OK, 0 rows affected (0.06 sec)
shell> ll ger*
-rw-r-----. 1 mysql mysql 32768 Jan 3 16:51 ger2_space.ibd # 未指定路径,存放于datadir目录
-rw-r-----. 1 mysql mysql 26 Jan 3 16:50 ger_space.isl # 指定了其他路径,存在isl链接文件
shell> cat ger_space.isl
/GeneralTest/ger_space.ibd # ibd文件真实存在的路径
mysql> select * from information_schema.innodb_sys_tablespaces where name='ger_space'\G
*************************** 1. row ***************************
SPACE: 96
NAME: ger_space
FLAG: 2304
FILE_FORMAT: Any
ROW_FORMAT: Any
PAGE_SIZE: 8192 -- page_size是8k
ZIP_PAGE_SIZE: 0
SPACE_TYPE: General -- General类型
FS_BLOCK_SIZE: 0
FILE_SIZE: 18446744073709551615
ALLOCATED_SIZE: 2
COMPRESSION: None
1 row in set (0.00 sec)
-- 2: 创建表
mysql> create table test_ger2 (a int) tablespace=ger_space;
Query OK, 0 rows affected (0.11 sec)
shell> ll test_ger* # 在datadir 的 burn_test 目录下
-rw-r-----. 1 mysql mysql 8554 Jan 3 16:41 test_ger1.frm
-rw-r-----. 1 mysql mysql 36 Jan 3 16:41 test_ger1.isl
-rw-r-----. 1 mysql mysql 8554 Jan 3 17:09 test_ger2.frm # 仅有一个frm文件
shell> ll /GeneralTest/
total 52
drwxr-x---. 2 mysql mysql 4096 Jan 3 16:41 burn_test
-rw-r-----. 1 mysql mysql 49152 Jan 3 17:09 ger_space.ibd # test_ger2的ibd文件其实存储在ger_space.ibd的通用表空间中
mysql> create table test_ger3 (a int) tablespace=ger_space; -- test_ger3 也存放在ger_space.ibd中
Query OK, 0 rows affected (0.09 sec)
mysql> create tablespace ger3_space add datafile '/GeneralTest/ger3_space.ibd' file_block_size=4096; -- 创建4K大小的General Space也是可以的
Query OK, 0 rows affected (0.06 sec)
-- 但是注意,如果设置了innodb_page_size,且大小不是file_block_size,那么在创建表的时候会报错
-- 这里的 file_block_size 就是 page_size
mysql> create table test_ger (a int) tablespace=ger3_space;
ERROR 1478 (HY000): InnoDB: Tablespace `ger3_space` uses block size 4096 and cannot contain a table with physical page size 8192
-- 既然无法创建表,那应该在创建general space时就应该报错
-- 后续涉及压缩表时可以使用
通过使用 General Space,一个表空间可以对应多张表,当对表进行 alter 等操作时,还是和原来一样,无需额外语法指定表空间位置,可以简单的理解为把多个表的 ibd 文件合并在一起了。
作者:殷建卫 链接:https://www.yuque.com/yinjianwei/vyrvkf/nkflkn 来源:殷建卫 - 架构笔记 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。