> 文档中心 > MySQL基础篇【第六篇】| 存储引擎、事务、索引、视图、DBA命令、数据库设计三范式

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表示数据不能重复

注意:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度!

结束语

今天的分享就到这里啦!快快通过下方链接注册加入刷题大军吧!各种大厂面试真题在等你哦!
💬刷题神器,从基础到大厂面试题👉点击跳转刷题网站进行注册学习