MySQL基础篇【第六篇】| 存储引擎、事务、索引、视图、DBA命令、数据库设计三范式
✅作者简介:大家好我是@每天都要敲代码,一位材料转码农的选手,希望一起努力,一起进步!
📃个人主页:@每天都要敲代码的个人主页
🔥系列专栏:MySQL专栏
💬推荐一款模拟面试、刷题神器,从基础到大厂面试题 👉点击跳转刷题网站进行注册学习
目录
一:存储引擎(了解)
1. 存储引擎的使用
2. 常见的存储引擎
二:事务(重要)
1. 概述
2. commit 与 rollback
3.事务的隔离级别
三:索引
四:视图(了解)
五:DBA命令 (了解)
1. 数据库的导入导出
六:数据库设计三范式 (重点)
一:存储引擎(了解)
1. 存储引擎的使用
(1)数据库中的各表均被(在创建表时)指定的存储引擎来处理
(2)服务器可用的引擎依赖于以下因素:
MySQL的版本
服务器在开发时如何被配置
启动选项
(3)查看一个表的建表引擎
show create table emp; --查看建表语句
建表的时候可以指定存储引擎,也可以指定字符集;mysql默认使用的存储引擎是InnoDB方式。默认采用的字符集是UTF8
(4)完整的建表语句
CREATE TABLE `t_x` ( `id` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
注意:在MySQL当中,凡是标识符是可以使用飘号括起来的。最好别用,不通用。
2. 常见的存储引擎
(1)什么是存储引擎呢?
存储引擎这个名字只有在mysql中存在Oracle中有对应的机制,但是不叫做存储引擎。
Oracle中没有特殊的名字,就是“表的存储方式”
mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。
每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。
(2)查看当前mysql支持的存储引擎?
select version();show engines \G-- mysql 5.5.36版本支持的存储引擎有9个
(3)常见的存储引擎
1、MyISAM
MyISAM这种存储引擎不支持事务。
MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。
MyISAM采用三个文件组织一张表:
xxx.frm(存储格式的文件)
xxx.MYD(存储表中数据的文件)
xxx.MYI(存储表中索引的文件)
优点:可被压缩,节省存储空间。并且可以转换为只读表,提高检索效率。
缺点:不支持事务。
2、InnoDB
优点:支持事务、行级锁、外键等。这种存储引擎数据的安全得到保障。
表的结构存储在xxx.frm文件中
数据存储在tablespace这样的表空间中(逻辑概念),无法被压缩,无法转换成只读
这种InnoDB存储引擎在MySQL数据库崩溃之后提供自动恢复机制。
InnoDB支持级联删除和级联更新,删除过更新父表,字表也跟着删除或者更新。
3、MEMORY
优点:查询速度最快。
缺点:不支持事务;数据容易丢失。因为所有数据和索引都是存储在内存当中的,一关机就没。 以前叫做HEPA引擎
二:事务(重要)
1. 概述
1、什么是事务(Transaction)?
一个事务是一个完整的业务逻辑单元,不可再分。
比如:银行账户转账,从A账户向B账户转账10000需要执行两条update语句:
update t_act set balance = balance - 10000 where actno = 'act-001'; update t_act set balance = balance + 10000 where actno = 'act-002';
以上两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败;要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。
2、和事务相关的语句只有:DML语句。(insert delete update)
为什么?因为它们这三个语句都是和数据库表当中的“数据”相关的。事务的存在是为了保证数据的完整性,安全性。
3、假设所有的业务都能使用1条DML语句搞定,还需要事务机制吗?
不需要事务;但实际情况不是这样的,通常一个“事务【业务】”需要多条DML语句共同联合完成。
4 、事物的原理假如一个事,需要先执行一条insert,执行一条update,最后执行一条delete,才算完成
开启事物机制:无论是执行insert语句、update、delete,把这个执行记录到数据库的操作历史当中(记录到缓存),并不会向文件保存一条数据,不会真正的修改硬盘上的数据
结束事物:提交事物或者回滚事物;提交事务会写到硬盘文件里,让文件真正发生改变;回滚事物,不会写到硬盘文件里,只会清空所有的历史记录;这样就能保持同时成功或者同时失败
5、事务的特性:ACID
A: 原子性(Atomicity):事务是最小的工作单元,不可再分。
C: 一致性(Consistency):事务必须保证多条DML语句同时成功或者同时失败。
I:隔离性(Isolation):事务A与事务B之间具有隔离。
D:持久性(Durability):持久性说的是最终数据必须持久化到硬盘文件中,事务才算成功的结束。6、关于事务之间的隔离性
事务隔离性存在隔离级别,理论上隔离级别包括4个:
第一级别:读未提交(read uncommitted)
对方事务还没有提交,我们当前事务可以读取到对方未提交的数据。
读未提交存在脏读(Dirty Read)现象:表示读到了脏的数据。
第二级别:读已提交(read committed)
对方事务提交之后的数据我方可以读取到。
这种隔离级别解决了: 脏读现象没有了。
读已提交存在的问题是:不可重复读。
第三级别:可重复读(repeatable read)
这种隔离级别解决了:不可重复读问题。
这种隔离级别存在的问题是:读取到的数据是幻象。
第四级别:序列化读/串行化读(serializable)
解决了所有问题。
效率低;需要事务排队。
oracle数据库默认的隔离级别是:读已提交。
mysql数据库默认的隔离级别是:可重复读!
2. commit 与 rollback
mysql事务默认情况下是自动提交的
什么是自动提交?只要执行任意一条DML语句则提交一次。
怎么关闭自动提交?start transaction;
(1)准备表
drop table if exists t_user;create table t_user( id int primary key auto_increment, username varchar(255));
(2)演示:mysql中的事务是支持自动提交的,只要执行一条DML,则提交一次
insert into t_user (username) values ('zs'); --插入数据select * from t_user; rollback; --已经自动提交,我们回滚,回不去了select * from t_user; --查询的结果和第一次查询一样
(3)演示:使用start transaction; 关闭自动提交机制
start transaction; --关闭自动回滚insert into t_user (username) values ('lisi'); --插入数据select * from t_user; rollback; --已经关闭了自动提交了,可以回滚过去select * from t_user; -- 回滚到插入上面这条数据之前的状态
(4)演示:手动提交
start transaction; --上面rollback事物就结束了,要重新关闭insert into t_user (username) values ('lisi'); --插入数据select * from t_user; commit; --提交rollback; --提交过后就回滚不过去了select * from t_user; -- 不能回滚
3.事务的隔离级别
(1)演示读未提交(read uncommitted)
-- 登录数据库,设置事务的隔离级别set global transaction isolation level read uncommitted; --设置事务的全局隔离级别为读未提交select @@global.tx_isolation; -- 查看事务的全局隔离级别-- 设置好隔离级别以后,关闭重新登录,开两个窗口use bjpowernode; -- 使用相同的数据库start transaction; --都关闭事务自动提交select * from t_user; --第一个窗口查看当前t_user的数据insert into t_user (username) values ('ww'); --第二个窗口插入这条数据-- 注意:此时事务关闭了自动提交,是自动提交状态select * from t_user; --第一个窗口再次查看当前t_user的数据,发现能读到未提交的,插入的ww数据
(2)演示读已提交(read committed)
-- 登录数据库,设置事务的隔离级别set global transaction isolation level read committed; --设置事务的全局隔离级别为读已提交select @@global.tx_isolation; -- 查看事务的全局隔离级别-- 设置好隔离级别以后,关闭重新登录,开两个窗口use bjpowernode; -- 使用相同的数据库start transaction; --都关闭事务自动提交select * from t_user; --第一个窗口查看当前t_user的数据insert into t_user (username) values ('zl'); --第二个窗口插入这条数据-- 注意:此时事务关闭了自动提交,是自动提交状态select * from t_user; --第一个窗口再次查看当前t_user的数据,读不到插入的zl数据commit; --第二个窗口提交select * from t_user; 第一个窗口再次查看当前t_user的数据,就能读到插入的zl数据
(3)演示可重复读(repeatable read)
-- 登录数据库,设置事务的隔离级别set global transaction isolation level repeatable read; --设置事务的全局隔离级别为可重复读select @@global.tx_isolation; -- 查看事务的全局隔离级别-- 设置好隔离级别以后,关闭重新登录,开两个窗口use bjpowernode; -- 使用相同的数据库start transaction; --都关闭事务自动提交select * from t_user; --第一个窗口查看当前t_user的数据delect from t_user; --第二个窗口删除这个表中的数据commit; --并提交select * from t_user; --第一个窗口再次查看当前t_user的数据,还是能查到,可重复读
(4)演示序列化读/串行化读(serializable)
-- 登录数据库,设置事务的隔离级别set global transaction isolation level serializable; --设置事务的全局隔离级别为可序列化select @@global.tx_isolation; -- 查看事务的全局隔离级别-- 设置好隔离级别以后,关闭重新登录,开两个窗口use bjpowernode; -- 使用相同的数据库start transaction; --都关闭事务自动提交select * from t_user; --第一个窗口查看当前t_user的数据,此时为空insert into t_user (username) values ('gh'); --第一个窗口插入数据,此时不提交select * from t_user; --第二个窗口再次查看当前t_user的数据,会卡住,等待提交后才能显示commit; --第一个窗口提交后,第一个窗口立马就能显示数据
三:索引
1、什么是索引?有什么用?
索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。
在数据库方面,查询一张表的时候有两种检索方式:
第一种方式:全表扫描
第二种方式:根据索引检索(效率很高)索引为什么可以提高检索效率呢?
其实最根本的原理是缩小了扫描的范围。
索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中的对象,也需要数据库不断的维护;是有维护成本的。比如:表中的数据经常被修改这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。
添加索引是给某一个字段,或者说某些字段添加索引。
select ename,sal from emp where ename = 'SMITH';
当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位。
2、怎么创建索引对象?怎么删除索引对象?
创建索引对象:create index 索引名称 on 表名(字段名);
删除索引对象:
drop index 索引名称 on 表名;
3、什么时候考虑给字段添加索引
* 数据量庞大。(根据客户的需求,根据线上的环境)
* 该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)
* 该字段经常出现在where子句中。(经常根据哪个字段查询)4、注意:主键和具有unique约束的字段自动会添加索引;根据主键查询效率较高,尽量根据主键检索。
5、查看sql语句的执行计划,explain:
drop table if exists t_emp;create table t_emp as select * from emp; --创建一个t_emp表
(1)没有索引,使用查询语句
explain select ename,sal from t_emp where sal = 5000;
(2)给薪资sal字段添加索引:
create index emp_sal_index on t_emp(sal);explain select ename,sal from t_emp where sal = 5000;
(3)删除索引,并再次查看drop index emp_sal_index on t_emp;explain select ename,sal from t_emp where sal = 5000;
6、索引底层采用的数据结构是:B + Tree
7、索引的实现原理
通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。select ename from emp where ename = 'SMITH';--通过索引转换为:select ename from emp where 物理地址 = 0x3;
8、索引的分类
单一索引:给单个字段添加索引
复合索引: 给多个字段联合起来添加1个索引
主键索引:主键上会自动添加索引
唯一索引:有unique约束的字段上会自动添加索引
....
9、索引什么时候失效select ename from emp where ename like '%A%'; --模糊查询
模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。
四:视图(了解)
1、什么是视图
站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。
视图实际上操作的还是原表的内容,不会提高检索效率
2、怎么创建视图?怎么删除视图?create view myview as select empno,ename from emp; --创建视图 drop view myview; --删除视图
注意:只有DQL查询语句才能以视图对象的方式创建出来
3、对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表),可以对视图进行CRUD操作。
4、面向视图操作
创建视图:
create view myview as select * from t_emp;select * from myview;
delete from t_emp where empno = 7369;select * from myview;select * from t_emp;
通过操作视图,可以操作原数据,删除视图myview里的7369那一行数据,我们发现原表t_emp的7369数据也被删除了
5、视图的作用
视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,java程序员只对视图对象进行CRUD:Create(增) Retrieve(检索) Update(修改) Delete(删除)
五:DBA命令 (了解)
1. 数据库的导入导出
1、将数据库当中的数据导出
在windows的dos命令窗口中执行:(导出整个库)mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123-- 导出整个bjpowernode数据库-- 注意是退出mysql,在dos命令窗口执行,并且没有分号结尾
在windows的dos命令窗口中执行:(导出指定数据库当中的指定表)
mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot –p123-- 只导出bjpowernode数据库中的emp表
2、导入数据
mysql -uroot -p123 -- 登录mysqlcreate database bjpowernode; -- 创建数据库use bjpowernode; -- 使用数据库source D:\bjpowernode.sql -- 利用source执行sql脚本导入数据
六:数据库设计三范式 (重点)
1、什么是设计范式
设计表的依据;按照这个三范式设计的表不会出现数据冗余
2、数据库设计三范式第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分
第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖主键,不能产生部分依赖
第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键,不能产生传递依赖
3、多对多、一对多、一对一
第一种情况:多对多;三张表、关系表两个外键
t_student学生表 sno(pk) sname --------------------- 1 张三 2 李四 3 王五t_teacher 讲师表 tno(pk) tname --------------------- 1 王老师 2 张老师 3 李老师t_student_teacher_relation 学生讲师关系表 id(pk) sno(fk) tno(fk) ---------------------------------- 1 1 3 2 1 1 3 2 2 4 2 3 5 3 1 6 3 3
第二种情况:一对多,两张表,多的表加外键
班级t_class cno(pk) cname -------------------------- 1 班级1 2 班级2学生t_student sno(pk) sname classno(fk) --------------------------------------------- 101 张1 1 102 张2 1 103 张3 2 104 张4 2 105 张5 2
第三种情况:一对一,两种方法:主键共享、外键唯一
第一种方案:主键共享
t_user_login 用户登录表 id(pk) username password -------------------------------------- 1 zs 123 2 ls 456t_user_detail 用户详细信息表 id(pk+fk) realname tel ------------------------------------------------ 1 张三 1111111111 2 李四 1111415621-- id既是主键又是外键,主键表示不唯一、不能重复;-- 外键表示数据只能来自t_user_login用户登录表的id
第二种方案:外键唯一
t_user_login 用户登录表 id(pk) username password -------------------------------------- 1 zs 123 2 ls 456t_user_detail 用户详细信息表 id(pk) realname tel userid(fk+unique) ----------------------------------------------------------- 1 张三 1111111111 2 2 李四 1111415621 1-- userid是外键并且唯一,外键表示数据来自t_user_login 用户登录表的id-- unique表示数据不能重复
注意:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度!
结束语
今天的分享就到这里啦!快快通过下方链接注册加入刷题大军吧!各种大厂面试真题在等你哦!
💬刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习