了解存储引擎我们先看下mysql的体系架构。
上图是mysql的逻辑架构图,可以看到分了几层。
第一层是大部分网路客户端工具,比如php,python ,JDBC等,主要功能就是连接处理,授权认证等,这层并不是mysql独有的。每个连接到mysql的客户端都会在服务端有个线程,这个连接的查询只会在这个线程中执行查询。
第二层是mysql服务层,包括了连接管理器,查询解析器,查询缓存,查询优化器,以及所有的mysql内置函数和sql接口。常用的DDL,DML语句都是在这层定义的,这层实现了所有跨存储引擎的功能:存储过程,存储函数,触发器,视图等等, 包含和存储引擎无关的特性(比如说常见的select语句,从文件系统中获取我们想要的数据这个具体的功能是由存储引擎实现),是mysql的核心服务功能所在的地方。
第三层,也就是文件系统层上面那一排就是mysql的存储引擎,者层被称之为存储引擎层,这也是mysql最有特点的就是它的插件式存储引擎,这种设计将数据库查询处理及数据的存储提取相分离,因为mysql中的数据存储和提取是由存储引擎来负责的,者层服务器通过API接口和存储引擎通信,而这些接口屏蔽了不同存储引擎的差异(比如非常出名的innodb存储引擎就是由第三方公司开发的),所以这种设计方式可以让我们在使用数据库的时候可以灵活的根据不同存储引擎的性能和特征来选择。
注意:
存储引擎是针对表的,一个数据库里不同的表可以选择不同的存储引擎。
MySQL常用的存储引擎的介绍
mysql存储引擎层多种存储引擎,它们各自的特性各不相同,包括InnoDB、MyISAM、Memory等。现在最常用的存储引擎是InnoDB,它从MySQL 5.5.5版本开始成为了mysql的默认存储引擎。
下面一张表格展示mysql存储引擎对比
查看当前mysql存储引擎信息
mysql> show engines;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| InnoDB | DEFAULT | Supports transactions, row-level locking, and foreign keys | YES | YES | YES |
| MRG_MYISAM | YES | Collection of identical MyISAM tables | NO | NO | NO |
| MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO |
| BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO |
| MyISAM | YES | MyISAM storage engine | NO | NO | NO |
| CSV | YES | CSV storage engine | NO | NO | NO |
| ARCHIVE | YES | Archive storage engine | NO | NO | NO |
| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO |
| FEDERATED | NO | Federated MySQL storage engine | NULL | NULL | NULL |
1.MyISAM存储引擎
MyISAM是mysql5.5之前的默认存储引擎,它是mysql最早使用的存储引擎之一,它也是大部分系统表,临时表(不是create table语句建的,这里是指在排序,分组等操作中,当记录数量超过一定大小的时候,由查询优化器建立的临时表)所采用的存储引擎。MyISAM存储引擎物理文件由MYD(数据文件)和MYI(索引文件)组成。
[root@localhost ~]# ls /usr/local/mysql/data/oa_2018/ | grep "^web_entry"
web_entry.frm 这个frm后缀是用来记录表的结构的文件
web_entry.MYD
web_entry.MYI
特性:
- 表损坏修复:可以对由于意外关闭导致采用MyISAM的表进行修复操作。可以使用mysql提供的check,repair语句检查修复表。
- 支持全文索引类型。
- 不支持事务,所以在写入数据的时候要对全表加锁,如果当写入并发较大,可能会造成锁阻塞。
- 存储格式:静态表,动态表,压缩表(当一张大表导入数据后不在进行修改操作了,这样可以压缩表,减少空间)。
- mysql版本小于5.0时,默认表大小4G,如果想存储大点表要修改MAX_Rows和AVG_ROW_LENGTH这两个参数。修改后表会重建,需要点时间。在高版本的mysql这个默认支持单表大小256TB。
- 仅在内存中保存索引。
适用场景:
- 非事务型应用。
- 只读类的应用。
- 空间类的应用(支持空间类的函数),比如地理数据。
示例:
创建一个mysiam引擎的表。
mysql> create table myiam_table(id int,name varchar()) engine=myisam;
Query OK, rows affected (0.34 sec)
使用语句检查修复表。
mysql> check table myiam_table;
+------------------------------+-------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+------------------------------+-------+----------+----------+
| oa_workflow_test.myiam_table | check | status | OK | 状态ok 说明表是正常的
+------------------------------+-------+----------+----------+
row in set (0.16 sec) mysql> repair table myiam_table;
+------------------------------+--------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+------------------------------+--------+----------+----------+
| oa_workflow_test.myiam_table | repair | status | OK |
+------------------------------+--------+----------+----------+
row in set (0.12 sec)
压缩表,可以使用myisampack打包压缩。压缩前先查看文件情况。
[root@localhost oa_workflow_test]# ls -l myiam_table*
-rw-r----- mysql mysql 6月 : myiam_table_5769.SDI
-rw-r----- mysql mysql 6月 : myiam_table.MYD
-rw-r----- mysql mysql 6月 : myiam_table.MYI
开始压缩
[root@localhost oa_workflow_test]# myisampack -b -f myiam_table.MYI f参数是强制压缩
Compressing myiam_table.MYD: ( records)
- Calculating statistics
- Compressing file
-%
压缩后我们在看下目录多了一个文件myiam_table.OLD,这个压缩之前myiam_table.MYI一个文件备份。
[root@localhost oa_workflow_test]# ls -l myiam_table*
-rw-r----- mysql mysql 6月 : myiam_table_5769.SDI
-rw-r----- mysql mysql 6月 : myiam_table.MYD
-rw-r----- mysql mysql 6月 : myiam_table.MYI
-rw-r----- mysql mysql 6月 : myiam_table.OLD
2.innodb存储引擎
innodb存储引擎是mysql5.5之后的默认存储引擎。是一种事务型存储引擎,支持事务的ACID特性,innodb的设计可以适合处理大量的小事务,小事务大部分情况下会被提交,很少被回滚。innodb在存储方面跟mysiam不一样,它有存储表空间的概念,数据是存储在表空间中的,具体怎么存储是由innodb_file_per_table这个参数定义的,参数为on则会为每个nnodb表建立idb为后缀的系统文件,比如tablename.idb,参数为off则把数据放在系统的表空间ibdataX(X表示数字)。现在默认都是优先使用innodb存储引擎。
innodb存储引擎特性:
- 支持事务。完全支持事务的ACID特性。innodb使用undo log 日志(存储未提交的事务来帮助未提交事务回滚和实现MVCC多版本并发控制(和oracle类似),这个文件可以独立表空间存在)和redo log日志(存储已经提交的事务,内容是顺序写入)来实现。
- 支持行级锁,读写很高效。在写操作时候锁定的资源更少,行级锁可以最大程度的支持并发。行级锁是由存储引擎自己实现的,mysql服务器不知道存储引擎锁的实现方式。注意:在没使用索引项时候会转成表级锁。
- 在内存中保存索引和数据。
查看默认存储引擎:
mysql> show variables like 'default_storage_engine';
+------------------------+--------+
| Variable_name | Value |
+------------------------+--------+
| default_storage_engine | InnoDB |
+------------------------+--------+
查看innodb_file_per_table的设置。
mysql> show variables like 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
mysql> create table table_innode(id int,name varchar()) engine ='innodb';
Query OK, rows affected (0.70 sec)
然后看下在文件系统中如何存储的。
[root@localhost webim]# ll
-rw-r----- mysql mysql 9月 conf_project_archives.ibd
-rw-r----- mysql mysql 6月 : table_innode.ibd
-rw-r----- mysql mysql 8月 table_innode.frm mysql8.0版本已经将这个文件取消掉了
如果将innodb_file_per_table设置成off,看看innodb如何存储。
mysql> set global innodb_file_per_table=off;
Query OK, rows affected (0.04 sec)
创建一张新表
mysql> create table my_innode_off(id int,name varchar()) engine ='innodb';
Query OK, rows affected (0.10 sec)
再次查看目录文件,发现这次只有frm文件。
[root@localhost webim]# ll
总用量
-rw-r----- mysql mysql 9月 conf_project_archives.ibd
-rw-r----- mysql mysql 6月 : table_innode.ibd
-rw-r----- mysql mysql 6月 : table_innode.frm
-rw-r----- mysql mysql 8月 my_innodb_off.frm
其实数据是存储在系统的共享表空间中,进入上一层目录,可以看见一个名为ibdata1的文件
[root@localhost webim]# cd ..
[root@localhost data]# ll
-rw-r-----. mysql mysql 6月 auto.cnf
drwxr-x--- mysql mysql 11月 db_kingnet_ganen
-rw-r----- mysql mysql 11月 db_kingnet_ganen_10.SDI
drwxr-x--- mysql mysql 10月 db_kingnet_oa
-rw-r----- mysql mysql 5月 : ib_buffer_pool
-rw-r-----. mysql mysql 6月 : ibdata1
系统表空间和独立表空间要如何选择。
我们可以对比下分析:
- 当删除数据表中不用的数据的时候,系统表空间无法简单的缩小文件的大小。
- 独立表空间可以通过optimize table命令来收缩系统文件,减少磁盘碎片。不需要重启数据库,不影响表的正常访问。
- 系统表空间由于只有一个文件,会产生IO瓶颈,如果对多个表数据刷新时候,从文件系统层面来看,是顺序进行的。而独立表空间,每张表都有自己的表空间文件,在添加数据的时候,可以利用多个文件增加IO处理的性能,所以对于频繁数据写入操作的系统不太适合独立表空间。