第七章·DBA-MySQL的存储引擎
存储引擎简介
- 文件系统
- 操作系统组织和存取数据的一种机制。
- 文件系统是一种软件
- 文件系统类型: ext2、3、4,xfs数据
- 不管使用什么文件系统,数据内容不会变化
- 不同的是,存储空间、大小、速度
- MySQL引擎
- 可以理解为,MySQL的"文件系统",只不过功能更强大
- MySQL引擎功能
- 除了可以提供基本的存取功能,还有更多功能:事务功能、锁定、备份和恢复、优化以及特殊功能
总之,存储引擎的各项特性就是为了保障数据库的安全和性能设计结构。
MySQL自带的存储引擎类型
MySQL 提供以下存储引擎:
01)InnoDB
02)MyISAM
03)MEMORY
04)ARCHIVE
05)FEDERATED
06)EXAMPLE
07)BLACKHOLE
08)MERGE
09)NDBCLUSTER
10)CSV
还可以使用第三方存储引擎:
01)MySQL当中插件式的存储引擎类型
02)MySQL的两个分支
03)perconaDB
04)mariaDB
## 查看所有的存储引擎
mysql[world]> show engines;
+--------------------+---------+
| Engine | Support |
+--------------------+---------+
| MRG_MYISAM | YES |
| CSV | YES |
| InnoDB | DEFAULT |
| BLACKHOLE | YES |
| MyISAM | YES |
| PERFORMANCE_SCHEMA | YES |
| ARCHIVE | YES |
| MEMORY | YES |
| FEDERATED | NO |
+--------------------+---------+
## 查看库中哪些表是InnoDB的存储引擎
mysql[world]> select TABLE_SCHEMA,TABLE_NAME,ENGINE from information_schema.tables
where engine='innodb';
## 查看库中哪些表是MyIsam的存储引擎
mysql[world]> select TABLE_SCHEMA,TABLE_NAME,ENGINE from information_schema.tables
where engine='myisam';
innodb和myisam的区别
物理上的区别
#进入mysql目录
[root@db01~l]# cd /application/mysql/data/mysql
#查看所有user的文件
[root@db01 mysql]# ll user.*
# 表结构文件
-rw-rw---- 1 mysql mysql 10684 Mar 6 2017 user.frm
# 数据文件
-rw-rw---- 1 mysql mysql 960 Aug 14 01:15 user.MYD
# 数据文件
-rw-rw---- 1 mysql mysql 2048 Aug 14 01:15 user.MYI
#进入word目录
[root@db01 world]# cd /application/mysql/data/world/
#查看所有city的文件
[root@db01 world]# ll city.*
# 表结构文件
# 数据文件
-rw-rw---- 1 mysql mysql 8710 Aug 14 16:23 city.frm
# 数据文件
-rw-rw---- 1 mysql mysql 688128 Aug 14 16:23 city.ibd
逻辑上区别
innodb存储引擎的简介
在MySQL5.5版本之后,默认的存储引擎,提供高可靠性和高性能。
优点:
01)事务安全(遵从 ACID)
02)MVCC(Multi-Versioning Concurrency Control,多版本并发控制)
03)InnoDB 行级别锁定
04)Oracle 样式一致非锁定读取
05)表数据进行整理来优化基于主键的查询
06)支持外键引用完整性约束
07)大型数据卷上的最大性能
08)将对表的查询与不同存储引擎混合
09)出现故障后快速自动恢复
10)用于在内存中缓存数据和索引的缓冲区池
innodb核心特性
重点:
MVCC
事务
行级锁
热备份
Crash Safe Recovery(自动故障恢复)
查看存储引擎
# 查看当前正在使用的存储引擎
mysql[zls]> SELECT @@default_storage_engine;
+--------------------------+
| @@default_storage_engine |
+--------------------------+
| InnoDB |
+--------------------------+
## 查看建表语句
mysql[lw]> show create table student;
mysql[lw]> select TABLE_SCHEMA,TABLE_NAME,ENGINE from information_schema.tables where
engine='innodb' and table_name='stu';
mysql[lw]> show table status like 'stu'\G
设置储存引擎
1.# 编辑MySQL配置文件
[mysqld]
default-storage-engine=<Storage Engine>
default-storage-engine=innodb
default-storage-engine=myisam
2.# 库内临时设置
mysql[(none)]> set global default_storage_engine=myisam;
3.# 建表时指定存储引擎
create table 表名(id int)engine='存储引擎名';
三.真实企业案例
项目背景:
公司原有的架构:一个展示型的网站,LAMT,MySQL5.1.77版本(MYISAM),50M数据量。
小问题不断:
1、表级锁:对表中任意一行数据修改类操作时,整个表都会锁定,对其他行的操作都不能同时进行。
2、不支持故障自动恢复(CSR):当断电时有可能会出现数据损坏或丢失的问题
如何解决:
1、提建议将现有的MYISAM引擎替换为Innodb,将版本替换为5.6.38 1)如果使用MYISAM会产生”小问题”,性能安全不能得到保证,使用innodb可以解决这个问题。
2)5.1.77版本对于innodb引擎支持不够完善,5.6.38版本对innodb支持非常完善了。
2、实施过程和注意要素
1)解决思路与过程
1.开会讨论,停机维护
2.将操作步骤,提前写在文档中
2.1准备新环境
新的CentOS系统
新的MySQL版本
配置文件优化好
服务启动好
3.关闭所有连接数据库的服务
systemctl stop php-fpm
systemctl stop tomcat
4.停数据库
systemctl stop mysqld
5.备份数据库中的全部数据
mysqldump -A -R --trigger --single-transaction --master-data=1
6.将备份的数据发送到新环境中
scp rsync
将表的myisam存储引擎改成innodb
mysql[zls]> alter table student engine='myisam';
mysql[zls]> alter table student charset='latin1';
## 方案一:
#!/bin/bash
for table in ` mysql -e 'show tables from zls'|awk 'NR>1'`;do
mysql -e "alter table zls.$table engine='myisam'";
done
## 方案二:
[root@db04 zls]# mysqldump -B zls > /tmp/zls.sql
:%s@ENGINE=MyISAM@ENGINE=InnoDB@g
7.将数据导入到新的数据库中
mysql -uroot -p123 < /tmp/zls.sql
8.将几台web服务器,连接到新库,做测试
9.应用割接
Innodb存储引擎-表空间介绍
表空间:
共享表空间
独立表空间
5.5版本以后出现共享表空间概念
表空间的管理模式的出现是为了数据库的储存更容易扩展
5.6版本中默认的是独立表空间
1.共享表空间
查看共享表空间
#物理查看
[root@db01 ~]# ll /application/mysql/data/
-rw-rw---- 1 mysql mysql 79691776 Aug 14 16:23 ibdata1
#命令行查看
mysql> show variables like '%path%';
+----------------------------------+------------------------+
| Variable_name | Value |
+----------------------------------+------------------------+
| innodb_data_file_path | ibdata1:12M:autoextend |
+----------------------------------+------------------------+
5.6版本中默认存储:
1.系统数据
2.undo
3.临时表
-rw-rw---- 1 mysql mysql 12582912 Aug 9 10:24 ibdata1 # 共享表空间
-rw-rw---- 1 mysql mysql 50331648 Aug 9 10:24 ib_logfile0 # redo log
-rw-rw---- 1 mysql mysql 50331648 Aug 2 14:45 ib_logfile1 # redo log
5.7版本中默认会将undo和临时表独立出来,5.6版本也可以独立,只不过需要在初始化的时候进行配置
-rw-r----- 1 mysql mysql 79691776 Aug 15 12:02 ibdata1 # 共享表空间
-rw-r----- 1 mysql mysql 50331648 Aug 15 12:02 ib_logfile0 # redo log
-rw-r----- 1 mysql mysql 50331648 Aug 3 17:10 ib_logfile1 # redo log
-rw-r----- 1 mysql mysql 12582912 Aug 15 12:01 ibtmp1 # 临时表
修改共享表空间
共享表空间,初始大小默认:12M:自动扩容
[root@db04 data]# vim /etc/my.cnf
[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend
innodb_data_file_path=ibdata1:76M;ibdata2:50M:autoextend
[root@db04 data]# systemctl restart mysqld
[root@db04 data]# du -sh ibdata2
-rw-r----- 1 mysql mysql 79691776 Aug 16 09:48 ibdata1
-rw-r----- 1 mysql mysql 52428800 Aug 16 09:48 ibdata2
2.独立表空间
对于用户自主创建的表,会采用此种模式,每个表由一个独立的表空间进行管理
1.查看独立表空间
#物理查看
[root@db01 ~]# ll /application/mysql/data/world/
-rw-r----- 1 mysql mysql 8710 Aug 13 12:00 city.frm # 表结构
-rw-r----- 1 mysql mysql 786432 Aug 13 12:00 city.ibd # 独立表空间
#命令行查看
mysql> show variables like '%per_table%';
+-----------------------+-------+
| Variable_name | Value |
+-----------------------+-------+
| innodb_file_per_table | ON |
+-----------------------+-------+
真实企业案例
在没有备份数据的情况下,突然断电导致表损坏,打不开数据库。
1.准备新环境,安装完数据库启动
2.将data目录备份出来导入新环境
[root@db01 ~]# cp -r /application/mysql/data/world/ /data/3307/data/
3.启动新数据库
[root@db01 ~]# mysqld_safe --defaults-file=/data/3307/my.cnf &
4.要知道建表语句,找开发要
mysql> 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;
5.删除新表的表空间文件
alter table world.country_new discard tablespace;
6.将旧表的表空间,拷贝成新表的表空间
[root@db02 world]# cp -a country.ibd country_new.ibd
# 光物理拷贝表空间会报错,country_new的表空间已经被删除
mysql> select * from country_new;
ERROR 1814 (HY000): Tablespace has been discarded for table 'country_new'
7.将新表的表空间,导入进去
mysql> alter table world.country_new import tablespace;
8.此时旧表还存在,数据依旧会写入旧表
# 两种解决方案:
- 跟开发说,去改代码,把所有要增删改成country表的代码改成country_new
- 删除已损坏的表,将新表改名为旧表名
[root@db02 world]# rm -f country.ibd
[root@db02 world]# rm -f country.frm
mysql> alter table country_new rename country;
8.旧业务先停机
9.使用binlog截取新数据,恢复到新环境中
10.业务应用割接到新环境
Innodb核心特性-事务
1.什么是事务
主要针对DML语句(update, delete, insert)
一组数据操作执行步骤,这些步骤被视为一个工作单元:
1)用于对多个语句进行分组
2)可以在多个客户机并发访问同一个表中的数据时使用
所有步骤都成功或都失败
1)如果所有步骤正常,则执行
2)如果步骤出现错误或不完整,则取消
2.事务的通俗理解
伴随着"交易"出现的数据库概念
我们理解的“交易”是什么?
1)物与物的交换(古代)
2)货币现金与实物的交换(现代1)
3)虚拟货币与实物的交换(现代2)
4)虚拟货币与虚拟实物交换(现代3)
数据库中的"交易"是什么
1)事务又是如何保证“交易”的“和谐”?
2)ACID
3.事务ACID特性
Atomic(原子性)
所有语句作为一个单元全部成功执行或全部取消。
Consistent(一致性)
如果数据库在事务开始时处于一致状态,则在执行该。事务期间将保留一致状态。
Isolated(隔离性)
事务之间不相互影响。
Durable(持久性)
事务成功完成后,所做的所有更改都会准确地记录在
数据库中。所做的更改不会丢失。
4.事务流程举例
5.事务的控制语句
start transaction(或 begin):显式开始一个新事务
savepoint:分配事务过程中的一个位置,以供将来引用
commit:永久记录当前事务所做的更改
rollback:取消当前事务所做的更改
rollback to savepoint:取消在 savepoint 之后执行的更改
release savepoint:删除 savepoint 标识符
set autocommit:为当前连接禁用或启用默认提交模式
## 开启事务语句
begin;
start transaction;
情况一:只要执行了DML语句,就会开启一个事务
insert update delete(这种情况因为是默认自动提交)
情况二:begin执行后,会开启一个事务
1.事务的生命周期
# 一个成功的事务生命周期
begin;
sql1
sql2
sql3
...
commit;
# 示例:
mysql> create table stu(id int,name varchar(10),sex enum('f','m'),money int);
mysql> begin;
mysql> insert into stu(id,name,sex,money) values(1,'zhang3','m',100), (2,'zhang4','m',110);
mysql> commit;
# 一个失败的事务生命周期
begin 开启一个事务
DML
DML
DML
DML
...
rollback;
# 示例 事务回滚
mysql> begin;
mysql> update stu set name='zhang3';
mysql> delete from stu;
mysql> rollback;
2.自动提交
#查看自动提交
mysql> show variables like 'autocommit';
#临时关闭
mysql> set autocommit=0;
#永久关闭
[root@db01 world]# vim /etc/my.cnf
[mysqld]
autocommit=0
3.事务隐式提交情况
在事务运行期间,手工执行begin的时候会自动提交上个事务
在事务运行期间,加入DDL、DCL操作会自动提交上个事务
在事务运行期间,执行锁定语句(lock tables、unlock tables)
load data infile
select for update
在autocommit=1的时候
事务的日志(CSR自动故障恢复)
Redo是什么?
redo,顾名思义"重做日志",是事务日志的一种
作用是什么?
在事务ACID过程中,实现的是“D”持久化的作用。
特性:WAL(Write Ahead Log)日志优先写
REDO:记录的是,内存数据页的变化过程
REDO工作过程
#执行步骤
update t1 set num=2 where num=1;
1)首先将t1表中num=1的行所在数据页加载到内存中buffer page
2)MySQL实例在内存中将num=1的数据页改成num=2
3)num=1变成num=2的变化过程会记录到,redo内存区域,也就是redo buffer page中
#提交事务执行步骤
commit;
1)当敲下commit命令的瞬间,MySQL会将redo buffer page写入磁盘区域redo log
2)当写入成功之后,commit返回ok
redo数据实例恢复过程
事务日志undo
undo是什么?
undo,顾名思义“回滚日志”,是事务日志的一种。
作用是什么?
在事务ACID过程中,实现的是“A”原子性的作用。当然CI的特性也和undo有关
故障可能遇到的三种情况:
1.提交了,commit,数据保存到磁盘上redo log中了,断电了数据还没有写入独立表空间
2.没提交,数据也保存到磁盘上redo log中了,断电了,数据还没有写入独立表空间
3.没有提交,数据也没有保存到 redo log中,断电了,数据还没写入独立表空间
事务中的锁
1)什么是“锁”?
“锁”顾名思义就是锁定的意思。
2)“锁”的作用是什么?
在事务ACID特性过程中,“锁”和“隔离级别”一起来实现“I”隔离性的作用。
排它锁:在事务操作期间,实现行级锁,保证数据的一致性
共享锁:在事务操作期间,其它事务不可以修改数据,但是可以查询数据
乐观锁:谁先提交以谁
悲观锁:只要事务执行期间,其它事务均无法查询
多版本并发控制(MVCC)
1)只阻塞修改类操作,不阻塞查询类操作
2)乐观锁的机制(谁先提交谁为准
锁的粒度
MyIsam:低并发锁(表级锁)
Innodb:高并发锁(行级锁)
事务的隔离级别
read uncommitted (RU级别:未提交读)
允许事务查看其他事务所进行的未提交更改
read committed (RC级别,已提交读)
允许事务查看其他事务所进行的已提交更改
repeatable read (RR级别)
确保每个事务的 SELECT 输出一致
InnoDB 的默认级别
serializable (串行化级别)
将一个事务的结果与其他事务完全隔离
#查看隔离级别
mysql> show variables like '%iso%';
#修改隔离级别为RU
[mysqld]
transaction_isolation=read-uncommit
mysql> use oldboy
mysql> select * from stu;
mysql> insert into stu(id,name,sex,money) values(2,'li4','f',123);
#修改隔离级别为RC
[mysqld]
transaction_isolation=read-commit
Comments | NOTHING