要想更好的学习存储引擎的话对于mysql组织结构一定要有清晰的认知了解,下面我们一起来看看吧!
## ![img](.\img\12.png)
1、连接层
```bash
1.验证用户的身份,用户名密码是否匹配
2.提供两种连接方式(TCP/IP连接、socket连接)
3.连接层提供了一个与sql层交互的线程
```
2、SQL层
```bash
1.接收连接层传过来的SQL语句
2.验证执行的SQL语法
3.验证SQL的语义(DDL,DML,DQL,DCL)
4.解析器:解析SQL语句,生成执行计划
5.优化器:将解析器传来的执行计划选择最优的一条执行
6.执行器:将最优的一条执行
6.1 与存储引擎层建立交互的线程
6.2 将要执行的sql发给存储引擎层
7.如果有缓存,则走缓存
8.记录日志(binlog)
```
3、存储引擎层
```bash
1.接收SQL层传来的语句
2.与磁盘交互,获取数据,返回给sql层
3.建立与sql层交互的线程
```
什么是存储引擎???
```
mysql中建立的库===>文件夹
库中建立的表===>文件
现实生活中我们用来存储数据的文件有不同的类型,每种文件类型对应各自不同的处理机制:比如处理文本用txt类型,处理表格用excel,处理图片用png等
数据库中的表也应该有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎,mysql根据不同的表类型会有不同的处理机制
存储引擎说白了就是如何存储数据、如何为存储的数据建立索引和如何更新、查询数据等技术的实现方
法。因为在关系数据库中数据的存储是以表的形式存储的,所以存储引擎也可以称为表类型(即存储和
操作此表的类型)
在Oracle 和SQL Server等数据库中只有一种存储引擎,所有数据存储管理机制都是一样的。而MySql
数据库提供了多种存储引擎。用户可以根据不同的需求为数据表选择不同的存储引擎,用户也可以根据
自己的需要编写自己的存储引擎
SQL 解析器、SQL 优化器、缓冲池、存储引擎等组件在每个数据库中都存在,但不是每 个数据库都有这么多存储引擎。MySQL 的插件式存储引擎可以让存储引擎层的开发人员设 计他们希望的存储层,例如,有的应用需要满足事务的要求,有的应用则不需要对事务有这 么强的要求 ;有的希望数据能持久存储,有的只希望放在内存中,临时并快速地提供对数据 的查询。
```
## 二 查看存储引擎信息
查看所有支持的存储引擎
```
MariaDB [(none)]> show engines\G
```
innodb存储引擎支持的核心特性
```
事务
行级锁:innodb支持行级锁,myisam是表级锁,锁的粒度越小并发能力越强
外键
MVCC 多版本并发控制
备份和恢复 innodb支持支持热备,myisam不支持
自动故障恢复 (CSR) Crash Safe Recovery
```
了解
```
01)InnoDB
支持事务,其设计目标主要面向联机事务处理(OLTP)的应用。其
特点是行锁设计、支持外键,并支持类似 Oracle 的非锁定读,即默认读取操作不会产生锁。
从 MySQL 5.5.8 版本开始是默认的存储引擎。如果应用对事务的完整性有比较高的要求,在并发条件下要求数据的一致性,数据操作除了插入和查询之外,还包括很多更新和删除操作,那么InnoDB存储引擎是比较合适的。InnoDB除了有效的降低由删除和更新导致的锁定,还可以确保事务的完整提交和回滚,对于类似计费系统或者财务系统等对数据准确要求性比较高的系统都是合适的选择。
InnoDB 存储引擎将数据放在一个逻辑的表空间中,这个表空间就像黑盒一样由 InnoDB 存储引擎自身来管理。从 MySQL 4.1(包括 4.1)版本开始,可以将每个 InnoDB 存储引擎的 表单独存放到一个独立的 ibd 文件中。此外,InnoDB 存储引擎支持将裸设备(row disk)用 于建立其表空间。
InnoDB 通过使用多版本并发控制(MVCC)来获得高并发性,并且实现了 SQL 标准 的 4 种隔离级别,默认为 REPEATABLE 级别,同时使用一种称为 netx-key locking 的策略来 避免幻读(phantom)现象的产生。除此之外,InnoDB 存储引擎还提供了插入缓冲(insert buffer)、二次写(double write)、自适应哈希索引(adaptive hash index)、预读(read ahead) 等高性能和高可用的功能。
对于表中数据的存储,InnoDB 存储引擎采用了聚集(clustered)的方式,每张表都是按 主键的顺序进行存储的,如果没有显式地在表定义时指定主键,InnoDB 存储引擎会为每一 行生成一个 6 字节的 ROWID,并以此作为主键。
InnoDB 存储引擎是 MySQL 数据库最为常用的一种引擎,Facebook、Google、Yahoo 等 公司的成功应用已经证明了 InnoDB 存储引擎具备高可用性、高性能以及高可扩展性。对其 底层实现的掌握和理解也需要时间和技术的积累。如果想深入了解 InnoDB 存储引擎的工作 原理、实现和应用,可以参考《MySQL 技术内幕:InnoDB 存储引擎》一书。
02)MyISAM
只是读取和插入,不做修改和删除使用这个,MyISAM不支持事务、表锁设计、支持全文索引,主要面向一些 OLAP 数 据库应用,在 MySQL 5.5.8 版本之前是默认的存储引擎(除 Windows 版本外)。数据库系统 与文件系统一个很大的不同在于对事务的支持,MyISAM 存储引擎是不支持事务的。究其根 本,这也并不难理解。用户在所有的应用中是否都需要事务呢?在数据仓库中,如果没有 ETL 这些操作,只是简单地通过报表查询还需要事务的支持吗?此外,MyISAM 存储引擎的 另一个与众不同的地方是,它的缓冲池只缓存(cache)索引文件,而不缓存数据文件,这与 大多数的数据库都不相同。
03)MEMORY 支持hash索引,使用redis替换
正如其名,Memory 存储引擎中的数据都存放在内存中,数据库重 启或发生崩溃,表中的数据都将消失。它非常适合于存储 OLTP 数据库应用中临时数据的临时表,也可以作为 OLAP 数据库应用中数据仓库的维度表,可以提供极快的访问。Memory的缺陷是对表的大小有限制,虽然数据库因为异常终止的话数据可以正常恢复,但是一旦数据库关闭,存储在内存中的数据都会丢失。
Memory 存储引擎默认使用哈希 索引,而不是通常熟悉的 B+ 树索引。
04)BLACKHOLE
黑洞存储引擎,可以应用于主备复制中的分发主库。
05)NDB 存储引擎
2003 年,MySQL AB 公司从 Sony Ericsson 公司收购了 NDB 存储引擎。 NDB 存储引擎是一个集群存储引擎,类似于 Oracle 的 RAC 集群,不过与 Oracle RAC 的 share everything 结构不同的是,其结构是 share nothing 的集群架构,因此能提供更高级别的 高可用性。NDB 存储引擎的特点是数据全部放在内存中(从 5.1 版本开始,可以将非索引数 据放在磁盘上),因此主键查找(primary key lookups)的速度极快,并且能够在线添加 NDB 数据存储节点(data node)以便线性地提高数据库性能。由此可见,NDB 存储引擎是高可用、 高性能、高可扩展性的数据库集群系统,其面向的也是 OLTP 的数据库应用类型。
06)Infobright 存储引擎
第三方的存储引擎。其特点是存储是按照列而非行的,因此非常 适合 OLAP 的数据库应用。其官方网站是 http://www.infobright.org/,上面有不少成功的数据 仓库案例可供分析。
07)NTSE 存储引擎
网易公司开发的面向其内部使用的存储引擎。目前的版本不支持事务, 但提供压缩、行级缓存等特性,不久的将来会实现面向内存的事务支持。
08)ARCHIVE
09)FEDERATED
10)EXAMPLE
11)MERGE
12)NDBCLUSTER
13)CSV
#还可以使用第三方存储引擎:
01)MySQL当中插件式的存储引擎类型
02)MySQL的两个分支
03)perconaDB
04)mariaDB
```
查看正在使用的存储引擎
```
show variables like 'storage_engine%';
或者
SELECT @@default_storage_engine;
```
查看innodb的表有哪些,表information_schema.tables
```
select table_schema,table_name,engine from information_schema.tables where engine='innodb';
```
查看myisam的表有哪些,表information_schema.tables
```
select table_schema,table_name,engine from information_schema.tables where engine='myisam';
```
查看表的存储引擎
```
SHOW CREATE TABLE db1.t1\G
或者
SELECT TABLE_NAME, ENGINE FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 't1' AND TABLE_SCHEMA = 'db1'\G
```
## 三 修改存储引擎
### 3.1 配置文件修改存储引擎
```bash
vim /etc/my.cnf
[mysqld]
default-storage-engine=innodb
innodb_file_per_table=1
```
### 3.2 临时修改存储引擎
```bash
#在MySQL命令行中临时设置
SET @@storage_engine=myisam
#查看
SELECT @@default_storage_engine;
```
### 3.3 建表时修改存储引擎
```bash
CREATE TABLE egon(id INT) ENGINE=myisam;
```
## 四 存储引擎实验
创建四个表,分别使用innodb,myisam,memory,blackhole存储引擎,进行插入数据测试
```
MariaDB [db1]> create table t1(id int)engine=innodb;
MariaDB [db1]> create table t2(id int)engine=myisam;
MariaDB [db1]> create table t3(id int)engine=memory;
MariaDB [db1]> create table t4(id int)engine=blackhole;
MariaDB [db1]> quit
[root@egon db1]# ls /var/lib/mysql/db1/ #发现后两种存储引擎只有表结构,无数据
db.opt t1.frm t1.ibd t2.MYD t2.MYI t2.frm t3.frm t4.frm
#memory,在重启mysql或者重启机器后,表内数据清空
#blackhole,往表内插入任何数据,都相当于丢入黑洞,表内永远不存记录
```
## 五、企业真实案例
### 1.项目背景:
```bash
公司原有的架构:一个展示型的网站,LAMT,MySQL5.1.77版本(MYISAM),50M数据量。
```
### 2.小问题不断:
```bash
1、表级锁:对表中任意一行数据修改类操作时,整个表都会锁定,对其他行的操作都不能同时进行。
2、不支持故障自动恢复(CSR):当断电时有可能会出现数据损坏或丢失的问题。
```
### 3.如何解决:
```bash
1、提建议将现有的MYISAM引擎替换为Innodb,将版本替换为5.6.38
1)如果使用MYISAM会产生”小问题”,性能安全不能得到保证,使用innodb可以解决这个问题。
2)5.1.77版本对于innodb引擎支持不够完善,5.6.38版本对innodb支持非常完善了。
2、实施过程和注意要素
```
#### 1)备份生产库数据(mysqldump)
```bash
# –triggers (默认导出触发器,使用–skip-triggers屏蔽导出)
# -R:–routines,导出存储过程以及自定义函数
[root@db01 ~]# mysqldump -uroot -p123 -A --triggers -R --master-data=2 >/tmp/full.sql
```
#### 2)准备一个5.6.38版本的新数据库
#### 3)对备份数据进行处理(将engine字段替换)
```bash
[root@db01 ~]# sed -i 's#ENGINE=MYISAM#ENGINE=INNODB#gi' /tmp/full.sql
#注意:修改之后导入数据库的时候mysql库会少表,因为有些系统表不能需改称innodb搜索引擎,所以迁移数据时,只迁移数据类型的库,不要迁移系统库
```
#### 4)将修改后的备份恢复到新库
```
mysql -uroot -p123 < /tmp/full.sql
```
#### 5)应用测试环境连接新库,测试所有功能
#### 6)停应用,将备份之后的生产库发生的新变化,补偿到新库
#### 7)应用割接到新数据库
## 六 Innodb存储引擎表空间
表空间的管理模式的出现是为了数据库的存储更容易扩展
5.5版本以后出现共享表空间概念
5.6版本中默认的是独立表空间
### 6.1 独立表空间
对于用户自主创建的表,会采用此种模式,每个表由一个独立的表空间进行管理
优点:
- 1.每个表都有自已独立的表空间,易于区分与管理
- 2.每个表的数据和索引都会存在自已的表空间中。
- 3.可以实现单表在不同的数据库中移动。
- 4.空间可以回收(除drop table操作处,表空不能自已回收)
- 4.1 Drop table操作自动回收表空间
- 4.2 如果对于统计分析或是日值表,删除大量数据后可以通过:alter table TableName engine=innodb;回缩不用的空间。
- 4.3 对于使innodb-plugin的Innodb使用turncate table也会使空间收缩。
- 4.4 对于使用独立表空间的表,不管怎么删除,表空间的碎片不会太严重的影响性能,而且还有机会处理。
缺点:
- 1、单表增加过大,如超过100个G。
- 2、相比较之下,使用独占表空间的效率以及性能会更高一点。
查看独立表空间
```bash
#物理查看
[root@db01 ~]# ll /application/mysql/data/world/
-rw-rw---- 1 mysql mysql 688128 Aug 14 16:23 city.ibd
#命令行查看
mysql> show variables like '%per_table%';
innodb_file_per_table=ON
```
企业案例
```bash
在没有备份数据的情况下,数据库突然断电导致表空间或者表结构损坏,打不开数据库。
```
从mysql5.6版本开始,引入了表空间传输的功能。可以把一张表从一个数据库移动到另一个数据库中或者另一台机器上。使用该功能必须满足如下条件:
- Mysql版本必须是5.6及以上
- 使用独立表空间方式,现在版本默认开启innodb_file_per_table
- 源库和目标库的page size必须一致,表结构必须一致
- 如果要做表的导出操作,该表只能进行只读操作
```
flush table test for export;
记住释放锁
unlock tables;
```
示例
```bash
# 1、安装mysql5.6+版
[root@localhost ~]# cat /etc/yum.repos.d/mysql.repo
[mysql56-community]
name=MySQL 5.6 Community Server
baseurl=http://repo.mysql.com/yum/mysql-5.6-community/el/7/$basearch/
enabled=1
gpgcheck=0
[root@localhost ~]# yum install mariadb-server* -y
[root@localhost ~]# yum install mariadb-* -y
[root@localhost ~]# systemctl start mysql
[root@localhost ~]# mysql -uroot
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.6.51 |
+-----------+
1 row in set (0.00 sec)
mysql>
# 2、设置独立表空间
vim /etc/my.cnf
[mysqld]
default-storage-engine=innodb
innodb_file_per_table=1
# 3、准备测试数据
create database egon;
use egon;
create table t1(id int);
insert t1 values(1),(2),(3);
# 4、将/var/lib/mysql/目录下的egon库打包,并删除目录egon
cd /var/lib/mysql/
tar czf egon.tar.gz egon/
rm -rf egon/
# 5、本机测试也行,重启mysql测试,或者把数据拷贝到另外一台数据库服务器进行解压测试
[root@localhost ~]# systemctl restart mysql
[root@localhost ~]# mysql -uroot -p
mysql> create database db1;
mysql> create table test(id int); -- 表结构与源应一致
Query OK, 0 rows affected (0.01 sec)
mysql> alter table test discard tablespace; -- 删除test.ibd文件
Query OK, 0 rows affected (0.00 sec)
mysql> exit
Bye
[root@localhost ~]# tar xvf egon.tar.gz
egon/
egon/db.opt
egon/t1.frm
egon/t1.ibd
[root@localhost ~]# cp -a egon/t1.ibd /var/lib/mysql/db1/test.ibd
[root@localhost ~]#
[root@localhost ~]# mysql -uroot -p
mysql> use db1;
mysql> alter table test import tablespace;
Query OK, 0 rows affected, 1 warning (0.01 sec)
mysql> select * from test;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)
# ps: 注意导入的ibd文件的属主属组与权限问题
```
### 6.2 共享表空间
#### 1)存储的内容
```bash
1.系统数据
2.undo redo,undo,事务日志,5.6中undo存储在共享表空间,redo是ib_logfile0,在MySQL5.7中,undo也是独立
3.临时表 查出来的数据生成一个表,临时的
```
#### 2)概念
```bash
类似于LVM逻辑卷,是动态扩展的
默认只有12M,会根据数据的量慢慢变越来越大
优点:可以将表空间分成多个文件存放到各个磁盘上(表空间文件大小不受表大小的限制,如一个表可以分布在不同的文件上)。数据和文件放在一起方便管理。
缺点:所有的数据和索引存放到一个文件中,虽然可以把一个大文件分成多个小文件,但是多个表及索引在表空间中混合存储,这样对于一个表做了大量删除操作后表空间中将会有大量的空隙,特别是对于统计分析,日值系统这类应用最不适合用共享表空间。
```
#### 3)查看共享表空间
```bash
mysql> show variables like '%path%';
+----------------------------------+------------------------+
| Variable_name | Value |
+----------------------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
| sha256_password_private_key_path | private_key.pem |
| sha256_password_public_key_path | public_key.pem |
| ssl_capath | |
| ssl_crlpath | |
+----------------------------------+------------------------+
5 rows in set (0.01 sec)
```
#### 4)修改共享表空间
```bash
#1.编辑配置文件
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
#配置一个就够用了,为什么要配置两个呢?
第一个共享表空间数据达到50M以后,他会往第二个表空间里面写数据,当第二个共享表空间数据也达到50M以后会动态扩容,这个文件会越来越大,就像日志一样;
这样就会导致一个问题,当越来越多的数据增加的时候,ibdata也会持续膨胀,有的达到几十G,上百G
那么,,当前存储数据的磁盘分区满的时候,要怎么样去扩展数据空间呢?
#2.修改完配置文件重启
[root@db03 ~]# systemctl start mysql
启动会报错或者启动不了
查看日志
[root@db03 ~]# less /usr/local/mysql/data/db03.err
2020-04-21 22:26:00 50917 [ERROR] InnoDB: Data file ./ibdata1 is of a different size 768 pages (rounded down to MB) than specified in t
he .cnf file 3200 pages!
#3.报错说明共享表空间大小不一致,我们要把共享表空间修改为当前共享表空间的大小才行
[root@db01 ~]# vim /etc/my.cnf
[mysqld]
innodb_data_file_path=ibdata1:12M;ibdata2:50M:autoextend
#4.修改后重启
[root@db03 ~]# systemctl start mysql
[root@db03 ~]# ps -ef | grep [m]ysql
mysql 51079 1 19 22:32 ? 00:00:00 /usr/local/mysql/bin/mysqld --defaults-file=/etc/my.cnf
```