MySQL基础篇 | 存储引擎、事务、索引、视图、DBA命令、数据库设计三范式
✅作者简介:大家好我是@每天都要敲代码,希望一起努力,一起进步!
📃个人主页:@每天都要敲代码的个人主页
🔥系列专栏:MySQL专栏
目录
一:存储引擎(了解)
1. 存储引擎的使用
(1)数据库中的各表均被(在创建表时)指定的存储引擎来处理
(2)服务器可用的引擎依赖于以下因素:
①MySQL的版本
②服务器在开发时如何被配置
③启动选项
(3)查看一个表的建表引擎
建表的时候可以指定存储引擎,也可以指定字符集;mysql默认使用的存储引擎是InnoDB方式,默认采用的字符集是UTF8。
show create table emp; --查看建表语句
(4)完整的建表语句
注意:在MySQL当中,凡是标识符是可以使用 飘号`` 括起来的,最好别用,不通用。例如:下面的t_x和id
CREATE TABLE `t_x` (
`id` int(11) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2. 常见的存储引擎
(1)什么是存储引擎呢?
存储引擎这个名字只有在mysql中存在Oracle中有对应的机制,但是不叫做存储引擎; Oracle中叫作“表的存储方式”!
mysql支持很多存储引擎,每一个存储引擎都对应了一种不同的存储方式。
每一个存储引擎都有自己的优缺点,需要在合适的时机选择合适的存储引擎。
(2)查看当前mysql支持的存储引擎?
select version();
show engines \G
-- 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语句同时成功或者同时失败,那么就需要使用数据库的“事务机制”。
update t_act set balance = balance - 10000 where actno = 'act-001';
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)准备表
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)什么是索引?有什么用?
索引就相当于一本书的目录,通过目录可以快速的找到对应的资源。在数据库方面,查询一张表的时候有两种检索方式:
第一种方式:全表扫描
第二种方式:根据索引检索(效率很高)
(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:
drop table if exists t_emp;
create table t_emp as select * from emp; --创建一个t_emp表
没有索引,使用查询语句
explain select ename,sal from t_emp where sal = 5000;
给薪资sal字段添加索引:
create index emp_sal_index on t_emp(sal);
explain select ename,sal from t_emp where sal = 5000;
删除索引,并再次查看
drop index emp_sal_index on t_emp;
explain select ename,sal from t_emp where sal = 5000;
(6)索引的实现原理
索引底层采用的数据结构是:B + Tree,通过B Tree缩小扫描范围,底层索引进行了排序,分区,索引会携带数据在表中的“物理地址”,最终通过索引检索到数据之后,获取到关联的物理地址,通过物理地址定位表中的数据,效率是最高的。
select ename from emp where ename = 'SMITH';
--通过索引转换为:
select ename from emp where 物理地址 = 0x3;
(7)索引的分类
单一索引:给单个字段添加索引
复合索引: 给多个字段联合起来添加1个索引
主键索引:主键上会自动添加索引
唯一索引:有unique约束的字段上会自动添加索引
....
(8)索引什么时候失效
模糊查询的时候,第一个通配符使用的是%,这个时候索引是失效的。
select ename from emp where ename like '%A%'; --模糊查询
四:视图(了解)
(1)什么是视图
站在不同的角度去看到数据。(同一张表的数据,通过不同的角度去看待)。
视图实际上操作的还是原表的内容,不会提高检索效率!
(2)怎么创建视图?怎么删除视图?
注意:只有DQL查询语句才能以视图对象的方式创建出来
create view myview as select empno,ename from emp; --创建视图
drop view myview; --删除视图
(3)对视图进行增删改查,会影响到原表数据。(通过视图影响原表数据的,不是直接操作的原表),可以对视图进行CRUD操作。
(4)面向视图操作
通过操作视图,可以操作原数据,删除视图myview里的7369那一行数据,我们发现原表t_emp的7369数据也被删除了
创建视图:
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;
(5)视图的作用
视图可以隐藏表的实现细节。保密级别较高的系统,数据库只对外提供相关的视图,java程序员只对视图对象进行CRUD:Create(增) Retrieve(检索) Update(修改) Delete(删除)
五:DBA命令 (了解)
1. 数据库的导入导出
(1)将数据库当中的数据导出,使用mysqldump命令!
在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)导入数据,使用source命令 !
mysql -uroot -p123 -- 登录mysql
create 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 456
t_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 456
t_user_detail 用户详细信息表
id(pk) realname tel userid(fk+unique)
-----------------------------------------------------------
1 张三 1111111111 2
2 李四 1111415621 1
-- userid是外键并且唯一,外键表示数据来自t_user_login 用户登录表的id
-- unique表示数据不能重复
注意:在实际的开发中,以满足客户的需求为主,有的时候会拿冗余换执行速度!
相关文章
- docker 搭建Mycat环境实现Mysql数据库的读写分离
- mysql创建数据库
- 【MySql】mysql 数据库数据订正
- mysql数据库移植
- 腾讯云备份数据库.xb恢复(mysql)
- PHP连接MySQL数据库的三种方式(mysql、mysqli、pdo)
- Mysql一个非常有用的内置函数今天碰到要把MySQL数据库中的varchar转换成date类型进
- 数据库基础之Mysql(3)mysql删除历史binlog
- 数据库内核月报 - 2015 / 05-MySQL · 引擎特性 · InnoDB redo log漫游
- Mysql 数据库默认值选 ‘‘“ 、Null和Empty String的区别
- paip.mysql 5.6 数据库 占用 内存 过多 的 解决方案
- Python MySQL - mysql-connector 驱动
- ❤️ 万字Python MySQL从入门到精通详细教程❤️ 再也不用担心学不会数据库了❤️
- MYSQL导入数据报错|MYSQL导入超大文件报错|MYSQL导入大数据库报错:2006 - MySQL server has gone away
- MySQL Study之--Mysql无法启动“mysql.host”
- 代码配置没有问题,为什么不回滚事务(要理解Mysql数据库引擎)
- MySQL重要知识点
- MYSQL提权之反弹SHELL——数据库提权属于webshell到管理员的纵向提权,本质还是利用udf提权,无非是在mysql自定义函数中使用了反弹shell而已
- MySQL远程连接报错2003-cant connection to mysql server on ‘IP’(10061 unknown error)
- MySQL数据库篇之mysql的快速启动和停止
- Linux下Mysql数据库的基础操作
- MySQL报错Column count of mysql.user is wrong. Expected 43, found 42. Created with MySQL 50568, now run
- 性能测试之mysql数据库如何调优?