总之,存储引擎的各项特性就是为了保障数据库的安全和性能设计结构。mysql
MySQL 提供如下存储引擎:
01)InnoDB
02)MyISAM
03)MEMORY
04)ARCHIVE
05)FEDERATED
06)EXAMPLE
07)BLACKHOLE
08)MERGE
09)NDBCLUSTER
10)CSVsql
还可使用第三方存储引擎:
01)MySQL当中插件式的存储引擎类型
02)MySQL的两个分支
03)perconaDB
04)mariaDB数据库
#查看当前MySQL支持的存储引擎类型 mysql> show engines #查看innodb的表有哪些 mysql> select table_schema,table_name,engine from information_schema.tables where engine='innodb'; #查看myisam的表有哪些 mysql> select table_schema,table_name,engine from information_schema.tables where engine='myisam';
物理上的区别:vim
#进入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
在MySQL5.5版本以后,默认的存储引擎,提供高可靠性和高性能。centos
优势:
01)事务安全(听从 ACID)
02)MVCC(Multi-Versioning Concurrency Control,多版本并发控制)
03)InnoDB 行级别锁定
04)Oracle 样式一致非锁定读取
05)表数据进行整理来优化基于主键的查询
06)支持外键引用完整性约束
07)大型数据卷上的最大性能
08)将对表的查询与不一样存储引擎混合
09)出现故障后快速自动恢复(csr)
10)用于在内存中缓存数据和索引的缓冲区池缓存
innodb核心特性安全
重点:
MVCC
事务
行级锁
热备份
Crash Safe Recovery(自动故障恢复)服务器
1)使用 SELECT 确认会话存储引擎架构
#查询默认存储引擎 SELECT @@default_storage_engine;
2)使用 SHOW 确认每一个表的存储引擎并发
#查看表的存储引擎 SHOW CREATE TABLE City\G SHOW TABLE STATUS LIKE 'CountryLanguage'\G
3)使用 INFORMATION_SCHEMA 确认每一个表的存储引擎
#查看表的存储引擎 mysql> select table_schema,table_name,engine from information_schema.tables \G SHOW CREATE TABLE City\G
1)在启动配置文件中设置服务器存储引擎
#在配置文件的[mysqld]标签下添加 [mysqld] default-storage-engine=<Storage Engine>
2)使用 SET 命令为当前客户机会话设置
#在MySQL命令行中临时设置 SET @@storage_engine=<Storage Engine>
(3)在 CREATE TABLE 语句指定
#建表的时候指定存储引擎 CREATE TABLE t (i INT) ENGINE = <Storage Engine>;

项目背景:
公司原有的架构:一个展现型的网站,LAMT,MySQL5.1.77版本(MYISAM),50M数据量。
小问题不断:
如何解决:
模拟环境
建表 mysql> create table test1(sid int,name varchar(11)) engine=myisam; mysql> create table test1(sid int,name varchar(11)) engine=myisam; mysql> create table test3(sid int,name varchar(11)) engine=myisam;
1)备份生产库数据(mysqldump)
[root@db01 ~]# mysqldump -uroot -p123 -A --triggers -R --master-data=2 >/tmp/full.sql #-A系统库 -B程序业务恢复库
2)准备一个5.6.38版本的新数据库
3)对备份数据进行处理(将engine字段替换)
[root@db01 ~]# sed -i 's#ENGINE=MYISAM#ENGINE=INNODB#g' /tmp/full.sql
4)将修改后的备份恢复到新库
mysql -uroot -p123 -h 10.0.0.52 </tmp/full.sql #导出表 mysqldump -uroot -p3308 -S /data/3308/data/mysql.sock --tables test student
5)应用测试环境链接新库,测试全部功能
6)停应用,将备份以后的生产库发生的新变化,补偿到新库
7)应用割接到新数据库
项目结果:
解决了”小问题”
5.5版本之后出现共享表空间概念
表空间的管理模式的出现是为了数据库的存储更容易扩展
5.6版本中默认的是独立表空间
一、共享表空间
innodb的全部数据保存在一个独立的表空间里面,而这个表空间能够由不少的文件组成,一个表能够跨越多个文件存在,因此其大小限制不在是文件大小限制,而是其自身的限制,默认最大限制为64tb,这个大小包括这个表的全部全部索引等相关的数据
1)查看共享表空间
#物理查看 [root@db01 ~]# ll /application/mysql/data/ -rw-rw---- 1 mysql mysql 79691776 Aug 14 16:23 ibdata1 #命令行查看 mysql> show variables like '%path%'; innodb_data_file_path =bdata1:12M:autoextend
5.6版本中默认存储:
1.系统数据
2.undo(事务的日志,5.7改配置文件能够独立出来)
3.临时表(查询临时生成的表)
5.7版本中默认会将undo和临时表独立出来,5.6版本也能够独立,只不过须要在初始化的时候进行配置
2)设置方法
#编辑配置文件 [root@db01 ~]# vim /etc/my.cnf [mysqld] innodb_data_file_path=ibdata1:76M;ibdata2:50M:autoextend
对于用户自主建立的表,会采用此种模式,每一个表由一个独立的表空间进行管理
1)查看独立表空间
#物理查看 [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
2)独立表空间
#物理查看 [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
企业案例
在没有备份数据的状况下,忽然断电致使表损坏,打不开数据库。
模拟环境
db01 db02
1.打包表
tar tar.world.gz world scp word /application/mysql/data/
2.多实例模拟测试
1)拷贝库目录到新库中
[root@db01 ~]# cp -r /application/mysql/data/world/ /data/3307/data/
2)启动新数据库
[root@db01 ~]# mysqld_safe --defaults-file=/data/3307/my.cnf &
3)登录数据库查看
mysql> show databases;
4)查询表中数据
mysql> select * from city; ERROR 1146 (42S02): Table 'world.city' doesn't exist
5)找到之前的表结构在新库中建立表
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;
6)删除表空间文件
mysql> alter table city_new discard tablespaces;
7)拷贝旧表空间文件
[root@db01 world]# cp -a /data/3307/data/world/city.ibd /data/3307/data/world/city_new.ibd #加-a不须要受权
8)受权
[root@db01 world]# chown -R mysql.mysql *
9)导入表空间
mysql> alter table city_new import tablespace;
10)物理删除旧表
[root@db02 world]# rm -fr city.*
11)改代表
mysql> alter table city1 rename city;
12)若是是新库,应用割接(修改代码连库的ip)
主要针对DML语句(update,delete,insert)
一组数据操做执行步骤,这些步骤被视为一个工做单元:
1)用于对多个语句进行分组
2)能够在多个客户机并发访问同一个表中的数据时使用
全部步骤都成功或都失败
1)若是全部步骤正常,则执行
2)若是步骤出现错误或不完整,则取消
伴随着“交易”出现的数据库概念。
咱们理解的“交易”是什么?
1)物与物的交换(古代)
2)货币现金与实物的交换(现代1)
3)虚拟货币与实物的交换(现代2)
4)虚拟货币与虚拟实物交换(现代3)
数据库中的“交易”是什么?
1)事务又是如何保证“交易”的“和谐”?
2)ACID
Atomic(原子性)
全部语句做为一个单元所有成功执行或所有取消。
Consistent(一致性)
若是数据库在事务开始时处于一致状态,则在执行该。
事务期间将保留一致状态。
Isolated(隔离性)
事务之间不相互影响。
Durable(持久性)
事务成功完成后,所作的全部更改都会准确地记录在
数据库中。所作的更改不会丢失。
** 4.事务流程举例**
5.事务的控制语句
以下:
START TRANSACTION(或 BEGIN):显式开始一个新事务
SAVEPOINT:分配事务过程当中的一个位置,以供未来引用
COMMIT:永久记录当前事务所作的更改
ROLLBACK:取消当前事务所作的更改
ROLLBACK TO SAVEPOINT:取消在 savepoint 以后执行的更改
RELEASE SAVEPOINT:删除 savepoint 标识符
SET AUTOCOMMIT:为当前链接禁用或启用默认 autocommit 模式
一个成功事务的生命周期
begin; sql1 sql2 sql3 ... commit;
一个失败事务的生命周期
begin; sql1 sql2 sql3 ... rollback;
#查看自动提交 mysql> show variables like 'autocommit'; #临时关闭 mysql> set autocommit=0; #永久关闭,(企业中通常不关闭) [root@db01 world]# vim /etc/my.cnf [mysqld] autocommit=0
1)成功事务
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;
2)事务回滚
mysql> begin; mysql> update stu set name='zhang3'; mysql> delete from stu; mysql> rollback;
1)如今版本在开启事务时,不须要手工begin,只要你输入的是DML语句,就会自动开启事务。
2)有些状况下事务会被隐式提交
例如:
在事务运行期间,手工执行begin的时候会自动提交上个事务
在事务运行期间,加入DDL、DCL操做会自动提交上个事务
在事务运行期间,执行锁定语句(lock tables、unlock tables)
load data infile
select for update (查询sql语句的执行结果)
在autocommit=1的时候
1)Redo是什么?
redo,顾名思义“重作日志”,是事务日志的一种。
2)做用是什么?
在事务ACID过程当中,实现的是“D”持久化的做用。
特性:WAL(Write Ahead Log)日志优先写
REDO:记录的是,内存数据页的变化过程
3)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
1)undo是什么?
undo,顾名思义“回滚日志”,是事务日志的一种。
_2)做用是什么?
在事务ACID过程当中,实现的是“A”原子性的做用。固然CI的特性也和undo有关
#redo位置 [root@db01 data]# ll /application/mysql/data/ -rw-rw---- 1 mysql mysql 50331648 Aug 15 06:34 ib_logfile0 -rw-rw---- 1 mysql mysql 50331648 Mar 6 2017 ib_logfile1 #undo位置 [root@db01 data]# ll /application/mysql/data/ -rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata1 -rw-rw---- 1 mysql mysql 79691776 Aug 15 06:34 ibdata2
在MySQL5.6版本中undo是在ibdata文件中,在MySQL5.7版本会独立出来。
1)什么是“锁”?
“锁”顾名思义就是锁定的意思。
2)“锁”的做用是什么?
在事务ACID特性过程当中,“锁”和“隔离级别”一块儿来实现“I”隔离性的做用。
排他锁:保证在多事务操做时,数据的一致性。
共享锁:保证在多事务工做期间,数据查询时不会被阻塞。
悲观锁:同时修改数据,谁先修改谁为准
乐观锁:谁先提交就是谁为准
1)只阻塞修改类操做,不阻塞查询类操做(排他锁,共享锁)
2)乐观锁的机制(谁先提交谁为准)
13.锁的粒度
MyIsam:低并发锁(表级锁)
Innodb:高并发锁(行级锁)
==行级锁.必须的有汇集索引(主键),不然仍是表级锁==
14.事务的隔离级别
四种隔离级别:
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
一个事务读到另一个事务尚未提交的数据,咱们称之为脏读。解决方法:把事务隔离级别调整到READ COMMITTED 一个事务前后读取同一条记录,但两次读取的数据不一样,咱们称之为不可重复读。解决方法:把事务隔离级别调整到REPEATABLE READ。 一个事务前后读取一个范围的记录,但两次读取的纪录数不一样,咱们称之为幻象读。解决方法:把事务隔离级别调整到SERIALIZABLE。 1, 脏读 一个事务读到另外一个事务,还没有提交的修改,就是脏读。这里所谓的修改,除了Update操做,不要忘了,还包括 Insert和Delete操做。 脏读的后果:若是后一个事务回滚,那么它所作的修改,通通都会被撤销。前一个事务读到的数据,就是垃圾数据。 举个例子:预订房间。 有一张Reservation表,往表中插入一条记录,来订购一个房间。 事务1:在Reservation表中插入一条记录,用于预订99号房间。 事务2:查询,还没有预约的房间列表,由于99号房间,已经被事务1预订。因此不在列表中。 事务1:信用卡付款。因为付款失败,致使整个事务回滚。 因此插入到Reservation 表中的记录并不置为持久(即它将被删除)。 如今99号房间则为可用。 因此,事务2所用的是一个无效的房间列表,由于99号房间,已经可用。若是它是最后一个没有被预约的房间,那么这将是一个严重的失误。 注:脏读的后果很严重。 2,不可重复读。 在同一个事务中,再次读取数据时【就是你的select操做】,所读取的数据,和第1次读取的数据,不同了。就是不可重复读。 举个例子: 事务1:查询99号房间是否为双人床房间。结果99号是。 事务2:将99号房间,改为单人床房间。 事务1:再次执行查询,99号房间不是双人房了。也就是说, 事务1,能够看到其余事务所作的修改。 在不可重复读,里面,能够看到其余事务所作的修改,而致使2次的查询结果再也不同样了。 这里的修改,是提交过的。也能够是没有提交的,这种状况同时也是脏读。 若是,数据库系统的隔离级别。容许,不可重复读。那么你启动一个事务,并作一个select查询操做。 查询到的数据,就有可能,和你第2次,3次...n次,查询到的数据不同。通常状况下,你只会作一次,select 查询,并以这一次的查询数据,做为后续计算的基础。由于容许出现,不可重复读。那么任何 时候,查询到的数据,都有可能被其余事务更新,查询的结果将是不肯定的。 注:若是容许,不可重复读,你的查询结果,将是不肯定的。一个不肯定的结果,你能容忍吗? 3,幻读 事务1读取指定的where子句所返回的一些行。而后,事务2插入一个新行,这个新行也知足事务1使用的查询 where子句。而后事务1再次使用相同的查询读取行,可是如今它看到了事务2刚插入的行。这个行被称为幻象, 由于对事务1来讲,这一行的出现是难以想象的。 举个例子: 事务1:请求没有预约的,双人床房间列表。99号在其中。 事务2:向Reservation表中插入一个新纪录,以预订99号房间,并提交。 事务1:再次请求有双人床的未预约的房间列表,99号房间,再也不位于列表中。 注:幻读,针对的是,Insert操做。若是事务2,插入的记录,没有提交。那么同时也是脏读。