9.MySQL的存储引擎
[toc]
存储引擎简介
- 文件系统
- 操作系统组织和存取数据的一种机制。
- 文件系统是一种软件。
- 文件系统类型
- 不管使用什么文件系统,数据内容不会变化
- 不同的是,存储空间、大小、速度。
- Linux的文件系统
- CentOS6文件系统:ext4
- CentOS7文件系统:xfs
- MySQL引擎
- 可以理解为,MySQL的“文件系统”,只不过功能更加强大。
- MySQL的存储引擎
- MySQL5.5版本之前:MyIsam
- MySQL5.5版本之后:Innodb
区别:myisam 表级锁,innodb行级锁
MySQL自带的存储引擎类型
MySQL 提供以下存储引擎
- InnoDB
- MyISAM
- MEMORY
- ARCHIVE
- FEDERATED
- EXAMPLE
- BLACKHOLE
- MERGE
- NDBCLUSTER
- CSV
还可以使用第三方存储引擎
- MySQL当中插件式的存储引擎类型
- MySQL的两个分支
- perconaDB
- mariaDB
1 | # 查看当前MySQL支持的存储引擎类型 |
innodb和myisam物理上的区别
1 | # 进入mysql目录 |
innodb存储引擎的简介
在MySQL5.5版本之后,默认的存储引擎,提供高可靠性和高性能。
**优点: **
- 事务安全(遵从 ACID)
- MVCC(Multi-Versioning Concurrency Control,多版本并发控制)
- InnoDB 行级别锁定
- Oracle 样式一致非锁定读取
- 表数据进行整理来优化基于主键的查询
- 支持外键引用完整性约束
- 大型数据卷上的最大性能
- 将对表的查询与不同存储引擎混合
- 出现故障后快速自动恢复
- 用于在内存中缓存数据和索引的缓冲区池
外键
引用另外一个表中的一列或多列数据,被引用的列应该具有主键约束或者唯一性约束(简单来说外键是另一个表的主键或者唯一约束)。
外键可以不唯一, 可以是空值,用来建立和加强两个表数据之间的连接
1 | # 有外键的建表语句 |
MySQL存储引擎核心特性
- 表空间
- 事务
- 锁
- CSR(自动故障恢复)
- MVCC(多版本并发控制)
- 隔离级别
查看存储引擎
1 | # 使用 SELECT 确认当前默认使用的存储引擎 |
存储引擎的设置
1 | # 建表指定存储引擎 |
Innodb存储引擎核心特性—表空间
表空间介绍
- 共享表空间
- 系统数据
- undo
- 临时表
- 独立表空间
- 用户真实数据
表空间位置
1 | # 数据目录下(共享表空间) |
Innodb存储引擎核心特性-事务
什么是事务
主要针对DML语句(update,delete,insert)
一组数据操作执行步骤,这些步骤被视为一个工作单元:
所有步骤都成功或都失败
- 如果所有步骤正常,则执行
- 如果步骤出现错误或不完整,则取消
事务的特性
- A:原子性
- 所有语句作为一个单元全部成功执行或全部取消。
- C:一致性
- 如果数据库在事务开始时处于一致状态,则在执行该。 事务期间将保留一致状态。
- I:隔离性
- 事务与事务之间是相互隔离的
- D:持久性
- 事务成功完成后,所做的所有更改都会准确地记录在数据库中。所做的更改不会丢失。
事务交易流程
SQL语句类别 DTL
Database Trasation Language(数据事务语言)
语法属性
1 | # 开启一个事务 |
注意:只要执行一条DML开始,就已经开启了一个事务,无需执行begin
DML自动commit
1 | # DML语句(默认自动开启commit) |
事务的生命周期流程
事务的隐式提交
- 即不执行’commit’或’rollback’的情况下自动提交事务
- 在事务执行期间,如果执行了DDL或者DCL语句,则自动提交上一个事务
- 在事务执行期间,如果执行了begin或者start transaction会自动提交上一个事务
- 在事务执行期间,如果执行了lock或unlock锁表语句,则会自动提交上一个事务
- 在事务执行期间,如果执行load data infile导出数据,则会提交上一个事务
- 在事务执行期间,如果执行select for update语句,则会提交上一个事务
- 在事务执行期间,如果设置了autocommit=1,则会提交上一个事务
Innodb存储引擎核心特性-自动故障恢复(CSR)
redo(重做日志)
- redo:
- 顾名思义“重做日志”,是事务日志的一种。
- 作用:
- 在事务ACID过程中,实现的是“D”持久化的作用。
redo log恢复数据过程
当我们执行commit之后,会将数据写入redo log
在一段时间内,redo buffer page中的数据会自动写入redo log
1 |
|
undo(回滚日志)
- undo:
- 顾名思义“回滚日志”,是事务日志的一种。
- 作用:
- 在事务ACID过程中,实现的是“A”原子性的作用。当然CI的特性也和undo有关
redo+undo(CSR)恢复数据过程
undo会记录commit的状态
数据执行了commit,data buffer page会写入到磁盘
数据没有执行commit,将数据将会回滚到begin时的状态
redo和undo的存储位置
1 | # redo位置 |
Innodb存储引擎核心特性-锁
- 锁:
- 顾名思义就是锁定的意思。
- 作用:
- 在事务ACID特性过程中,“锁”和“隔离级别”一起来实现“I”隔离性的作用。
锁的力度
- Innodb:
- 行级锁(前提:该表中,必须有主键索引)
- myisam:
- 表级锁
锁分类
- 排它锁:
- 事务执行期间,阻塞其他事务的修改操作
- 共享锁:
- 事务执行期间,不阻塞其他事务的查询操作
- 乐观锁:
- 事务执行期间,谁先提交以谁为准
- 悲观锁:
- 事务执行期间,其他事务无法查看该数据的变化
Innodb存储引擎核心特性-多版本并发控制(MVCC)
多版本并发控制(MVCC)的构成
多版本并发控制是由三个锁构成:
- 排它锁
- 只阻塞修改类操作,不阻塞查询类操作
- 共享锁
- 例如所有用户可以查询同一表的数据
- 乐观锁
- 乐观锁的机制(谁先提交谁为准)
事务的四种隔离级别
- RU:Read Uncommit(未提交读)
- 允许事务查看其他事务所进行的未提交更改
- RC:Read Commit(提交读)
- 允许事务查看其他事务所进行的已提交更改
- RR:Repeatable Read(可重复读——InnoDB 的默认级别)**
- 确保每个事务的 select 输出一致
- SERIALIZABLE(串行化)
- 将一个事务的结果与其他事务完全隔离
1 | # 查看隔离级别(默认为RR级别) |
企业案例1
项目背景:
公司原有的架构:一个展示型的网站,LAMT,MySQL5.1.77版本(MYISAM),50M数据量。
公司问题:
- 表级锁:对表中任意一行数据修改类操作时,整个表都会锁定,对其他行的操作都不能同时进行。
- 不支持故障自动恢复(CSR):当断电时有可能会出现数据损坏或丢失的问题。
如何解决:
提建议将现有的MYISAM引擎替换为Innodb,将版本替换为5.6.38
- 如果使用MYISAM会产生”小问题”,性能安全不能得到保证,使用innodb可以解决这个问题。
- 5.1.77版本对于innodb引擎支持不够完善,5.6.38版本对innodb支持非常完善了。
实施过程和注意要素准备新环境
1
2
3
4
5
6
7
8
9
10
11# 安装MySQL5.6或5.7
# mysqldump备份出旧库的所有表
mysqldump -uroot -p123@qqdianCOM -B world > /tmp/world.sql
# 替换
vim /tmp/world.sql
:%s#ENGINE=MyISAM#ENGINE=InnoDB#g
# 数据恢复到新环境
MySQL < /tmp/world.sql
企业案例2
项目背景:
在没有备份数据的情况下,突然断电导致表损坏,打不开数据库。
如何解决:
准备新环境
1
mysqld_safe --defaults-file=/data/3307/my.cnf &
拷贝库目录到新库中
1
cp -r /application/mysql/data/world/ /data/3307/data/
恢复表
恢复city表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33# 用以前的表结构在新库中建表(找DBA或开发要)
show create table world.city;
## 删掉外键创建语句
CREATE TABLE `city` (
`ID` int(11) NOT NULL AUTO_INCREMENT,
`Name` char(35) NOT NULL DEFAULT '',
`CountryCode` char(3) NOT NULL DEFAULT '',
`District` char(20) NOT NULL DEFAULT '',
`Population` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`ID`),
KEY `CountryCode` (`CountryCode`),
KEY `idx_city` (`Population`,`CountryCode`),
CONSTRAINT `city_ibfk_1` FOREIGN KEY (`CountryCode`) REFERENCES `country` (`Code`)
) ENGINE=InnoDB AUTO_INCREMENT=4080 DEFAULT CHARSET=latin1;
# 删除表空间文件
alter table city_new discard tablespace;
# 拷贝旧表空间文件
cp -a city.ibd city_new.ibd
# 授权
chown -R mysql.mysql *
# 导入表空间
alter table city_new import tablespace;
# 物理删除损坏的表文件
rm -fr city.frm
rm -fr city.ibd
# 改表名
alter table city_new rename city;恢复country表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36# 用以前的表结构在新库中建表(找DBA或开发要)
show create table world.country;
CREATE TABLE `country_new` (
`Code` char(3) NOT NULL DEFAULT '',
`Name` char(52) NOT NULL DEFAULT '',
`Continent` enum('Asia','Europe','North America','Africa','Oceania','Antarctica','South America') NOT NULL DEFAULT 'Asia',
`Region` char(26) NOT NULL DEFAULT '',
`SurfaceArea` float(10,2) NOT NULL DEFAULT '0.00',
`IndepYear` smallint(6) DEFAULT NULL,
`Population` int(11) NOT NULL DEFAULT '0',
`LifeExpectancy` float(3,1) DEFAULT NULL,
`GNP` float(10,2) DEFAULT NULL,
`GNPOld` float(10,2) DEFAULT NULL,
`LocalName` char(45) NOT NULL DEFAULT '',
`GovernmentForm` char(45) NOT NULL DEFAULT '',
`HeadOfState` char(60) DEFAULT NULL,
`Capital` int(11) DEFAULT NULL,
`Code2` char(2) NOT NULL DEFAULT '',
PRIMARY KEY (`Code`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
# 删除表空间文件
alter table country_new discard tablespace;
# 拷贝旧表空间文件
cp -a country.ibd country_new.ibd
# 导入表空间
alter table country_new import tablespace;
# 物理删除损坏的表文件
rm -fr country.frm
rm -fr country.ibd
# 改表名
alter table country_new rename country;恢复countrylanguage表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26# 用以前的表结构在新库中建表(找DBA或开发要)
show create table world.countrylanguage;
CREATE TABLE `countrylanguage_new` (
`CountryCode` char(3) NOT NULL DEFAULT '',
`Language` char(30) NOT NULL DEFAULT '',
`IsOfficial` enum('T','F') NOT NULL DEFAULT 'F',
`Percentage` float(4,1) NOT NULL DEFAULT '0.0',
PRIMARY KEY (`CountryCode`,`Language`),
KEY `CountryCode` (`CountryCode`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
# 删除表空间文件.
alter table countrylanguage_new discard tablespace;
# 拷贝旧表空间文件
cp -a countrylanguage.ibd countrylanguage_new.ibd
# 导入表空间
alter table countrylanguage_new import tablespace;
# 物理删除损坏的表文件
rm -fr countrylanguage.frm
rm -fr countrylanguage.ibd
# 改表名
alter table countrylanguage_new rename countrylanguage;
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 奥利奥の麦旋风!