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


    ✅作者简介:大家好我是@每天都要敲代码,希望一起努力,一起进步!
    📃个人主页:@每天都要敲代码的个人主页
    🔥系列专栏:MySQL专栏

    目录

    一:存储引擎(了解)

    1. 存储引擎的使用

    2. 常见的存储引擎

    二:事务(重要)

    1. 概述

    2. commit 与 rollback

    3.事务的隔离级别

    三:索引 

    四:视图(了解)

    五:DBA命令 (了解)

    1. 数据库的导入导出

    六:数据库设计三范式 (重点)


    一:存储引擎(了解)

    1. 存储引擎的使用

    (1)数据库中的各表均被(在创建表时)指定的存储引擎来处理

    (2)服务器可用的引擎依赖于以下因素:

    ①MySQL的版本

    ②服务器在开发时如何被配置

    ③启动选项

    (3)查看一个表的建表引擎

    建表的时候可以指定存储引擎,也可以指定字符集;mysql默认使用的存储引擎是InnoDB方式,默认采用的字符集是UTF8。

    show create table emp; --查看建表语句

    (4)完整的建表语句
      注意:在MySQL当中,凡是标识符是可以使用 飘号`` 括起来的,最好别用,不通用。

      例如:下面的t_x和id

    1.      CREATE TABLE `t_x` (
    2.          `id` int(11) DEFAULT NULL
    3.       ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

    2. 常见的存储引擎

    (1)什么是存储引擎呢?
    存储引擎这个名字只有在mysql中存在

    Oracle中有对应的机制,但是不叫做存储引擎; Oracle中叫作“表的存储方式”

    mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。
    每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。
    (2)查看当前mysql支持的存储引擎?

    1. select version();
    2. show engines \G
    3. -- mysql 5.5.36版本支持的存储引擎有9个

    (3)常见的存储引擎 

    1、MyISAM

    MyISAM是mysql最常用的存储引擎,但是这种引擎不是默认的。

    MyISAM这种存储引擎不支持事务!
    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语句: 

     以下两条DML语句必须同时成功,或者同时失败,不允许出现一条成功,一条失败;要想保证以上的两条DML语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。        

    1.    update t_act set balance = balance - 10000 where actno = 'act-001';
    2.    update t_act set balance = balance + 10000 where actno = 'act-002';

    (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)准备表

    1. drop table if exists t_user;
    2. create table t_user(
    3. id int primary key auto_increment,
    4. username varchar(255)
    5. );

    (2)演示:mysql中的事务是支持自动提交的,只要执行一条DML,则提交一次

    1. insert into t_user (username) values ('zs'); --插入数据
    2. select * from t_user;
    3. rollback; --已经自动提交,我们回滚,回不去了
    4. select * from t_user; --查询的结果和第一次查询一样

    (3)演示:使用start transaction; 关闭自动提交机制

    1. start transaction; --关闭自动回滚
    2. insert into t_user (username) values ('lisi'); --插入数据
    3. select * from t_user;
    4. rollback; --已经关闭了自动提交了,可以回滚过去
    5. select * from t_user; -- 回滚到插入上面这条数据之前的状态

     (4)演示:手动提交

    1. start transaction; --上面rollback事物就结束了,要重新关闭
    2. insert into t_user (username) values ('lisi'); --插入数据
    3. select * from t_user;
    4. commit; --提交
    5. rollback; --提交过后就回滚不过去了
    6. select * from t_user; -- 不能回滚

    3.事务的隔离级别

     (1)演示读未提交(read uncommitted)

    1. -- 登录数据库,设置事务的隔离级别
    2. set global transaction isolation level read uncommitted; --设置事务的全局隔离级别为读未提交
    3. select @@global.tx_isolation; -- 查看事务的全局隔离级别
    4. -- 设置好隔离级别以后,关闭重新登录,开两个窗口
    5. use bjpowernode; -- 使用相同的数据库
    6. start transaction; --都关闭事务自动提交
    7. select * from t_user; --第一个窗口查看当前t_user的数据
    8. insert into t_user (username) values ('ww'); --第二个窗口插入这条数据
    9. -- 注意:此时事务关闭了自动提交
    10. select * from t_user; --第一个窗口再次查看当前t_user的数据,发现能读到未提交的,插入的ww数据

     

    (2)演示读已提交(read committed)

    1. -- 登录数据库,设置事务的隔离级别
    2. set global transaction isolation level read committed; --设置事务的全局隔离级别为读已提交
    3. select @@global.tx_isolation; -- 查看事务的全局隔离级别
    4. -- 设置好隔离级别以后,关闭重新登录,开两个窗口
    5. use bjpowernode; -- 使用相同的数据库
    6. start transaction; --都关闭事务自动提交
    7. select * from t_user; --第一个窗口查看当前t_user的数据
    8. insert into t_user (username) values ('zl'); --第二个窗口插入这条数据
    9. -- 注意:此时事务关闭了自动提交,是自动提交状态
    10. select * from t_user; --第一个窗口再次查看当前t_user的数据,读不到插入的zl数据
    11. commit; --第二个窗口提交
    12. select * from t_user; 第一个窗口再次查看当前t_user的数据,就能读到插入的zl数据

     

    (3)演示可重复读(repeatable read)

    1. -- 登录数据库,设置事务的隔离级别
    2. set global transaction isolation level repeatable read; --设置事务的全局隔离级别为可重复读
    3. select @@global.tx_isolation; -- 查看事务的全局隔离级别
    4. -- 设置好隔离级别以后,关闭重新登录,开两个窗口
    5. use bjpowernode; -- 使用相同的数据库
    6. start transaction; --都关闭事务自动提交
    7. select * from t_user; --第一个窗口查看当前t_user的数据
    8. delect from t_user; --第二个窗口删除这个表中的数据
    9. commit; --并提交
    10. select * from t_user; --第一个窗口再次查看当前t_user的数据,还是能查到,可重复读

    (4)演示序列化读/串行化读(serializable)

    1. -- 登录数据库,设置事务的隔离级别
    2. set global transaction isolation level serializable; --设置事务的全局隔离级别为可序列化
    3. select @@global.tx_isolation; -- 查看事务的全局隔离级别
    4. -- 设置好隔离级别以后,关闭重新登录,开两个窗口
    5. use bjpowernode; -- 使用相同的数据库
    6. start transaction; --都关闭事务自动提交
    7. select * from t_user; --第一个窗口查看当前t_user的数据,此时为空
    8. insert into t_user (username) values ('gh'); --第一个窗口插入数据,此时不提交
    9. select * from t_user; --第二个窗口再次查看当前t_user的数据,会卡住,等待提交后才能显示
    10. commit; --第一个窗口提交后,第一个窗口立马就能显示数据

    三:索引 

    (1)什么是索引?有什么用?
    索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。在数据库方面,查询一张表的时候有两种检索方式:
    第一种方式:全表扫描
    第二种方式:根据索引检索(效率很高)

    (2)索引为什么可以提高检索效率呢?
    其实索引最根本的原理是缩小了扫描的范围。
    索引虽然可以提高检索效率,但是不能随意的添加索引,因为索引也是数据库当中的对象,也需要数据库不断的维护;是有维护成本的。

    比如:表中的数据经常被修改这样就不适合添加索引,因为数据一旦修改,索引需要重新排序,进行维护。

    添加索引是给某一个字段,或者说某些字段添加索引,例如:

    当ename字段上没有添加索引的时候,以上sql语句会进行全表扫描,扫描ename字段中所有的值。当ename字段上添加索引的时候,以上sql语句会根据索引扫描,快速定位!

     select ename,sal from emp where ename = 'SMITH';

    (3)怎么创建索引对象?怎么删除索引对象?

    创建索引对象:           

    create index 索引名称 on 表名(字段名);

      删除索引对象:            

    drop index 索引名称 on 表名;

    (4)什么时候考虑给字段添加索引
    ①数据量庞大。(根据客户的需求,根据线上的环境)
    ②该字段很少的DML操作。(因为字段进行修改操作,索引也需要维护)
    ③该字段经常出现在where子句中。(经常根据哪个字段查询)

    注意:主键和具有unique约束的字段自动会添加索引;根据主键查询效率较高,尽量根据主键检索。

    (5)查看sql语句的执行计划,explain:       

    1. drop table if exists t_emp;
    2. create table t_emp as select * from emp; --创建一个t_emp表

    没有索引,使用查询语句       

    explain select ename,sal from t_emp where sal = 5000;


      

    给薪资sal字段添加索引:

    1. create index emp_sal_index on t_emp(sal);
    2. explain select ename,sal from t_emp where sal = 5000;


    删除索引,并再次查看

    1. drop index emp_sal_index on t_emp;
    2. explain select ename,sal from t_emp where sal = 5000;

    (6)索引的实现原理
    索引底层采用的数据结构是:B + Tree,通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。           

    1. select ename from emp where ename = 'SMITH';
    2. --通过索引转换为:
    3. select ename from emp where 物理地址 = 0x3;

    (7)索引的分类
    单一索引:给单个字段添加索引
    复合索引: 给多个字段联合起来添加1个索引
    主键索引:主键上会自动添加索引
    唯一索引:有unique约束的字段上会自动添加索引

     ....

    (8)索引什么时候失效      

    模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。

     select ename from emp where ename like '%A%'; --模糊查询

    四:视图(了解)

    (1)什么是视图
    站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。
    视图实际上操作的还是原表的内容,不会提高检索效率!

    (2)怎么创建视图?怎么删除视图? 

    注意:只有DQL查询语句才能以视图对象的方式创建出来         

    1.  create view myview as select empno,ename from emp; --创建视图
    2.  drop view myview; --删除视图

    (3)对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表),可以对视图进行CRUD操作。

    (4)面向视图操作

    通过操作视图,可以操作原数据,删除视图myview里的7369那一行数据,我们发现原表t_emp的7369数据也被删除了

    创建视图:

    1. create view myview as select * from t_emp;
    2. select * from myview;

    1. delete from t_emp where empno = 7369;
    2. select * from myview;
    3. select * from t_emp;

        

    (5)视图的作用
    视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,java程序员只对视图对象进行CRUD:Create(增) Retrieve(检索) Update(修改) Delete(删除)

    五:DBA命令 (了解)

    1. 数据库的导入导出

    (1)将数据库当中的数据导出,使用mysqldump命令!

    在windows的dos命令窗口中执行:(导出整个库)            

    1. mysqldump bjpowernode>D:\bjpowernode.sql -uroot -p123
    2. -- 导出整个bjpowernode数据库
    3. -- 注意是退出mysql,在dos命令窗口执行,并且没有分号结尾

    在windows的dos命令窗口中执行:(导出指定数据库当中的指定表)           

    1.  mysqldump bjpowernode emp>D:\bjpowernode.sql -uroot –p123
    2. -- 只导出bjpowernode数据库中的emp表

    (2)导入数据,使用source命令   !     

    1. mysql -uroot -p123 -- 登录mysql
    2. create database bjpowernode; -- 创建数据库
    3. use bjpowernode; -- 使用数据库
    4. source D:\bjpowernode.sql -- 利用source执行sql脚本导入数据

    六:数据库设计三范式 (重点)

    (1)什么是设计范式
    设计范式就是设计表的依据;按照这个三范式设计的表不会出现数据冗余

    (2)数据库设计三范式

    第一范式:任何一张表都应该有主键,并且每一个字段原子性不可再分

    第二范式:建立在第一范式的基础之上,所有非主键字段完全依赖主键不能产生部分依赖
    第三范式:建立在第二范式的基础之上,所有非主键字段直接依赖主键不能产生传递依赖
      

    (3)多对多、一对多、一对一   

    第一种情况:多对多;三张表、关系表两个外键         

    1. t_student学生表
    2.             sno(pk)        sname
    3.             ---------------------
    4.             1                张三
    5.             2                李四
    6.             3                王五
    7. t_teacher 讲师表
    8.             tno(pk)        tname
    9.             ---------------------
    10.             1                王老师
    11.             2                张老师
    12.             3                李老师
    13. t_student_teacher_relation 学生讲师关系表
    14.             id(pk)        sno(fk)        tno(fk)
    15.             ----------------------------------
    16.             1                1                3
    17.             2                1                1
    18.             3                2                2
    19.             4                2                3
    20.             5                3                1
    21.             6                3                3

     第二种情况:一对多,两张表,多的表加外键     

    1. 班级t_class
    2.             cno(pk)            cname
    3.             --------------------------
    4.             1                    班级1
    5.             2                    班级2
    6. 学生t_student
    7.             sno(pk)            sname            classno(fk)
    8.             ---------------------------------------------
    9.             101                张1                1
    10.             102                张2                1
    11.             103                张3                2
    12.             104                张4                2
    13.             105                张5                2

    第三种情况:一对一,两种方法:主键共享、外键唯一

    第一种方案:主键共享         

    1. t_user_login  用户登录表
    2.             id(pk)        username            password
    3.             --------------------------------------
    4.             1                zs                    123
    5.             2                ls                    456
    6. t_user_detail 用户详细信息表
    7.             id(pk+fk)     realname            tel            
    8.             ------------------------------------------------
    9.             1                张三                1111111111
    10.             2                李四                1111415621
    11. -- id既是主键又是外键,主键表示不唯一、不能重复;
    12. -- 外键表示数据只能来自t_user_login用户登录表的id


    第二种方案:外键唯一      

    1. t_user_login  用户登录表
    2.             id(pk)        username            password
    3.             --------------------------------------
    4.             1                zs                    123
    5.             2                ls                    456
    6. t_user_detail 用户详细信息表
    7.             id(pk)       realname            tel           userid(fk+unique)
    8.             -----------------------------------------------------------
    9.             1                张三           1111111111        2
    10.             2                李四           1111415621        1
    11. -- userid是外键并且唯一,外键表示数据来自t_user_login  用户登录表的id
    12. -- unique表示数据不能重复

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

  • 相关阅读:
    Jackson ImmunoResearch通过 SDS-PAGE 进行蛋白质分离
    express脚手架安装
    Java(98)Java执行时,报错Unsupported major.minor version 52.0
    第九章(1):循环神经网络与pytorch示例(RNN实现股价预测)
    企业大数据发展面临问题之存算分离技术思考
    c++ 服务器编程tcp
    安卓手机磁盘空间不足怎样导出数据?
    一文读懂python中mpi4py的所有基础使用
    Element-ui el-table 使用 SortableJS 实现表格拖拽
    单相半波可控整流电路仿真设计(任务书+lunwen+MATLAB仿真源文件)
  • 原文地址:https://blog.csdn.net/m0_61933976/article/details/126355237