【MySQL】知识点总结

1.什么是MySQL?

MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),使用最常用的数据库管理语言–结构化查询语言(SQL)进行数据库管理。MySQL是开放源代码的,因此任何人都可以在General Public License的许可下下载并根据个性化的需要对其进行修改。

2.MySQL常用的存储引擎有什么?它们有什么区别?

  1. InnoDB
    InnoDB是MySQL的默认存储引擎,支持事务、行锁和外键等操作。
  2. MyISAM
    MyISAM是MySQL5.1版本前的默认存储引擎,MyISAM的并发性比较差,不支持事务和外键等操作,默认的锁的粒度为表级锁。

MySQL 存储引擎(MyISAM、InnoDB、NDBCluster)

3.数据库的三大范式

  • 第一范式:确保每列保持原子性,数据表中的所有字段值都是不可分解的原子值。
    比如字段 userInfo: 广东省 10086 ,依照第一范式必须拆分成 userInfo: 广东省userTel: 10086两个字段。

  • 第二范式:首先要满足第一范式,另外包含两部分内容,一是表必须有一个主键;二是非主键列必须完全依赖于主键,而不能只依赖于主键的一部分。
    举个例子。假定选课关系表为student_course(student_no, student_name, age, course_name, grade, credit),主键为(student_no, course_name)。其中学分完全依赖于课程名称,姓名年龄完全依赖学号,不符合第二范式,会导致数据冗余(学生选n门课,姓名年龄有n条记录)、插入异常(插入一门新课,因为没有学号,无法保存新课记录)等问题。
    应该拆分成三个表:学生:student(stuent_no, student_name, 年龄);课程:course(course_name, credit);选课关系:student_course_relation(student_no, course_name, grade)。

  • 第三范式:首先要满足第二范式,另外非主键列必须直接依赖于主键,不能存在传递依赖。即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。
    假定学生关系表为Student(student_no, student_name, age, academy_id, academy_telephone),主键为"学号",其中学院id依赖于学号,而学院地点和学院电话依赖于学院id,存在传递依赖,不符合第三范式。
    可以把学生关系表分为如下两个表:学生:(student_no, student_name, age, academy_id);学院:(academy_id, academy_telephone)。

  • 2NF和3NF的区别?
    2NF依据是非主键列是否完全依赖于主键,还是依赖于主键的一部分。
    3NF依据是非主键列是直接依赖于主键,还是直接依赖于非主键。

4.事务

4.1 什么是事务(Innodb引擎条件下 NDB Cluster也支持但不常用)

事务是作为一个单元的一组有序的数据库操作。 如果组中的所有操作都成功则认为事务成功。即使只有一个操作失败,事务也不成功。如果所有操作完成,事务则提交,其修改将作用于所有其他数据库进程。如果一个操作失败,则事务将回滚,该事务所有操作的影响都将取消。

  1. 只有在Mysql中使用了Innodb数据库引擎的数据库或表才支持事务
  2. 事务处理可以用来维护数据库的完整性,保证成批的SQL语句要么全部执行,要么都不执行。
  3. 事务用来管理 insert update delete语句

在这里插入图片描述

语法:

START TRANSACTION - 开启事务
SAVEPOINT - 指令用于创建保留点。
ROLLBACK TO - 指令用于回滚到指定的保留点;如果没有设置保留点,则回退到 START TRANSACTION 语句处。
COMMIT - 提交事务。

举个🌰

-- 撤销表 user
DROP TABLE IF EXISTS user;

-- 创建表 user
CREATE TABLE user (
  id int(10) unsigned NOT NULL COMMENT 'Id',
  username varchar(64) NOT NULL DEFAULT 'default' COMMENT '用户名',
  password varchar(64) NOT NULL DEFAULT 'default' COMMENT '密码',
  email varchar(64) NOT NULL DEFAULT 'default' COMMENT '邮箱'
) COMMENT='用户表';
-- 开始事务
START TRANSACTION;

-- 插入操作 A
INSERT INTO `user`
VALUES (1, 'root1', 'root1', 'xxxx@qq.com');

-- 创建保留点 updateA
SAVEPOINT updateA;

-- 插入操作 B
INSERT INTO `user`
VALUES (2, 'root2', 'root2', 'xxxx@qq.com');

-- 回滚到保留点 updateA
ROLLBACK TO updateA;

-- 提交事务,只有操作 A 生效
COMMIT;

MySQL 默认采用自动提交模式(AUTO COMMIT)。也就是说,如果不显式使用 START TRANSACTION 语句来开始一个事务,那么每个查询操作都会被当做一个事务并自动提交。

4.2 事务的四大特性

事务特性ACID:原子性(Atomicity)一致性(Consistency)隔离性(Isolation)持久性(Durability)

  • 原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。
  • 一致性是指一个事务执行之前和执行之后都必须处于一致性状态。比如a与b账户共有1000块,两人之间转账之后无论成功还是失败,它们的账户总和还是1000。
  • 隔离性。一个事务所做的修改在最终提交以前,对其它事务是不可见的。
  • 持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

4.3 @Transactional

@Transactional 详解
@Transactional(rollbackFor=Exception.class)详解

  • 在项目中,@Transactional(rollbackFor=Exception.class),如果类加了这个注解,那么这个类里面的方法抛出异常,就会回滚,数据库里面的数据也会回滚。
  • 在@Transactional注解中如果不配置rollbackFor属性,那么事物只会在遇到RuntimeException的时候才会回滚,加上rollbackFor=Exception.class,可以让事物在遇到非运行时异常时也回滚
  • @Transactional 实质是使用了 JDBC 的事务来进行事务控制的
  • @Transactional 基于 Spring 的动态代理的机制

4.4 事务隔离级别

  • 读未提交(READ UNCOMMITTED)

读未提交,顾名思义,就是一个事务可以读取另一个未提交事务的数据。
事例:老板要给程序员发工资,程序员的工资是3.6万/月。但是发工资时老板不小心按错了数字,按成3.9万/月,该钱已经打到程序员的账户,但是事务还没有提交,就在这时,程序员去查看自己这个月的工资,发现比往常多了3千元,以为涨工资了非常高兴。但是老板及时发现了不对,马上回滚差点就提交了的事务,将数字改成3.6万再提交。
分析:实际程序员这个月的工资还是3.6万,但是程序员看到的是3.9万。他看到的是老板还没提交事务时的数据。这就是脏读。

  • 读已提交(READ COMMITTED)

一个事务只能看见已经提交事务所做的改变。可避免脏读的发生。
读已提交,顾名思义,就是一个事务要等另一个事务提交后才能读取数据。
事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他买单时(程序员事务开启),收费系统事先检测到他的卡里有3.6万,就在这个时候!!程序员的妻子要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待妻子转出金额事务提交完)。程序员就会很郁闷,明明卡里是有钱的…
分析:这就是读提交,若有事务对数据进行更新(UPDATE)操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两个相同的查询却返回了不同数据,这就是不可重复读。

  • 可重复读(REPEATABLE READ) 默认的

可重复读,就是在开始读取数据(事务开启)时,不再允许修改操作
事例:程序员拿着信用卡去享受生活(卡里当然是只有3.6万),当他埋单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有3.6万。这个时候他的妻子不能转出金额了。接下来收费系统就可以扣款了。
分析:可重复读可以解决不可重复读问题。写到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

  • 序列化(SERIALIZABLE)

Serializable 是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

在这里插入图片描述
在这里插入图片描述

@Transactional(isolation = Isolation.READ_UNCOMMITTED):读取未提交数据(会出现脏读, 不可重复读) 基本不使用
@Transactional(isolation = Isolation.READ_COMMITTED):读取已提交数据(会出现不可重复读和幻读)
@Transactional(isolation = Isolation.REPEATABLE_READ):可重复读(会出现幻读)
@Transactional(isolation = Isolation.SERIALIZABLE):序列化

在这里插入图片描述

查看隔离级别:
select @@transaction_isolation;

设置隔离级别:
set session transaction isolation level read uncommitted;

事务举🌰
查询方法需要使用事务吗?

5. 生产环境数据库一般用的什么隔离级别呢?

生产环境大多使用RC(读已提交)。为什么不是RR(可重复读)呢?

可重复读(Repeatable Read),简称为RR读已提交(Read Commited),简称为RC

  • 缘由一:在RR隔离级别下,存在间隙锁,导致出现死锁的几率比RC大的多!
  • 缘由二:在RR隔离级别下,条件列未命中索引会锁表!而在RC隔离级别下,只锁行!

也就是说,RC的并发性高于RR。

并且大部分场景下,不可重复读问题是可以接受的。毕竟数据都已经提交了,读出来本身就没有太大问题!
互联网mysql应该选什么事务隔离级别

6.编码和字符集的关系

我们平时可以在编辑器上输入各种中文英文字母,但这些都是给人读的,不是给计算机读的,其实计算机真正保存和传输数据都是以二进制0101的格式进行的。

那么就需要有一个规则,把中文和英文字母转化为二进制。其中d对应十六进制下的64,它可以转换为01二进制的格式。于是字母和数字就这样一一对应起来了,这就是ASCII编码格式。

它用一个字节,也就是8位来标识字符,基础符号有128个,扩展符号也是128个。也就只能表示下英文字母和数字。

这明显不够用。于是,为了标识中文,出现了GB2312的编码格式。为了标识希腊语,出现了greek编码格式,为了标识俄语,整了cp866编码格式。

为了统一它们,于是出现了Unicode编码格式,它用了2~4个字节来表示字符,这样理论上所有符号都能被收录进去,并且它还完全兼容ASCII的编码,也就是说,同样是字母d,在ASCII用64表示,在Unicode里还是用64来表示。

但不同的地方是ASCII编码用1个字节来表示,而Unicode用则两个字节来表示。

同样都是字母d,unicode比ascii多使用了一个字节,如下:

D   ASCII:           01100100
D Unicode:  00000000 01100100

可以看到,上面的unicode编码,前面的都是0,其实用不上,但还占了个字节,有点浪费。如果我们能做到该隐藏时隐藏,这样就能省下不少空间,按这个思路,就是就有了UTF-8编码。

总结一下,按照一定规则把符号和二进制码对应起来,这就是编码。而把n多这种已经编码的字符聚在一起,就是我们常说的字符集。

比如utf-8字符集就是所有utf-8编码格式的字符的合集。

总结一下,按照一定规则把符号和二进制码对应起来,这就是编码。而把n多这种已经编码的字符聚在一起,就是我们常说的字符集。

比如utf-8字符集就是所有utf-8编码格式的字符的合集。

想看下mysql支持哪些字符集。可以执行 show charset;

7.utf8和utf8mb4的区别

上面提到utf-8是在unicode的基础上做的优化,既然unicode有办法表示所有字符,那utf-8也一样可以表示所有字符,为了避免混淆,我在后面叫它大utf8。

mysql支持的字符集中有utf8和utf8mb4。

先说utf8mb4编码,mb4就是most bytes 4的意思,从上图最右边的Maxlen可以看到,它最大支持用4个字节来表示字符,它几乎可以用来表示目前已知的所有的字符。

再说mysql字符集里的utf8,它是数据库的默认字符集。但注意,此utf8非彼utf8,我们叫它小utf8字符集。为什么这么说,因为从Maxlen可以看出,它最多支持用3个字节去表示字符,按utf8mb4的命名方式,准确点应该叫它utf8mb3。

utf8 就像是阉割版的utf8mb4,只支持部分字符。比如emoji表情,它就不支持。

而mysql支持的字符集里,第三列,collation,它是指字符集的比较规则。

比如,"debug"和"Debug"是同一个单词,但它们大小写不同,该不该判为同一个单词呢。

这时候就需要用到collation了。

通过SHOW COLLATION WHERE Charset = 'utf8mb4';可以查看到utf8mb4下支持什么比较规则。

在这里插入图片描述
如果collation = utf8mb4_general_ci,是指使用utf8mb4字符集的前提下,挨个字符进行比较(general),并且不区分大小写(_ci,case insensitice)。

这种情况下,"debug"和"Debug"是同一个单词。

如果改成collation=utf8mb4_bin,就是指挨个比较二进制位大小。

于是"debug"和"Debug"就不是同一个单词。

那utf8mb4对比utf8有什么劣势吗?

我们知道数据库表里,字段类型如果是char(2)的话,里面的2是指字符个数,也就是说不管这张表用的是什么编码的字符集,都能放上2个字符。

而char又是固定长度,为了能放下2个utf8mb4的字符,char会默认保留2*4(maxlen=4)= 8个字节的空间。

如果是utf8mb3,则会默认保留 2 * 3 (maxlen=3) = 6个字节的空间。也就是说,在这种情况下,utf8mb4会比utf8mb3多使用一些空间。

8.索引

8.1 什么是索引?

索引是存储引擎用于提高数据库表的访问速度的一种数据结构。它可以比作一本字典的目录,可以帮你快速找到对应的记录。

索引一般存储在磁盘的文件中,它是占用物理空间的。

8.2 索引的优缺点

优点:

  • 加快数据查找的速度
  • 为用来排序或者是分组的字段添加索引,可以加快分组和排序的速度
  • 加快表与表之间的连接

缺点:

  • 建立索引需要占用物理空间
  • 会降低表的增删改的效率,因为每次对表记录进行增删改,需要进行动态维护索引,导致增删改时间变长

8.3 索引的作用?

数据是存储在磁盘上的,查询数据时,如果没有索引,会加载所有的数据到内存,依次进行检索,读取磁盘次数较多。有了索引,就不需要加载所有数据,因为B+树的高度一般在2-4层,最多只需要读取2-4次磁盘,查询速度大大提升。

8.4 什么情况下需要建索引?

经常用于查询的字段
经常用于连接的字段建立索引,可以加快连接的速度
经常需要排序的字段建立索引,因为索引已经排好序,可以加快排序查询速度

8.5 什么情况下不建索引?

  • where条件中用不到的字段不适合建立索引。
  • 表记录较少。比如只有几百条数据,没必要加索引。
  • 需要经常增删改。需要评估是否适合加索引。
  • 参与列计算的列不适合建索引。
  • 区分度不高的字段不适合建立索引,如性别,只有男/女/未知三个值。加了索引,查询效率也不会提高。

8.6 索引的数据结构

索引的数据结构主要有B+树和哈希表,对应的索引分别为B+树索引和哈希索引。InnoDB引擎的索引类型有B+树索引和哈希索引,默认的索引类型为B+树索引。

8.6.1 B+树索引

B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B树的平衡性,并且通过顺序访问指针来提高区间查询的性能。
在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1
在这里插入图片描述
// TODO

8.6.2 Hash索引和B+树索引的区别?

  1. 哈希索引不支持排序,因为哈希表是无序的。
  2. 哈希索引不支持范围查找。
  3. 哈希索引不支持模糊查询及多列索引的最左前缀匹配。
  4. 因为哈希表中会存在哈希冲突,所以哈希索引的性能是不稳定的,而B+树索引的性能是相对稳定的,每次查询都是从根节点到叶子节点。

附录1

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
数字编号越大,优先级越高,优先级高的运算符先进行计算。可以看到,赋值运算符的优先级最低,使用“()”括起来的表达式的优先级最高。

附录2

1.大彬一个不错的知识分享
2. 慢SQL优化 https://blog.csdn.net/Blue_Pepsi_Cola/article/details/128453015
3. 丁奇MYSQL45讲
4. MySQL的Explain关键字查看是否使用索引
5. MySQL优化之explain详解
6. MySQL面试八股文背诵版
7. Mysql 经典50题练习
8. 另一个Mysql八股文

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

boy快快长大

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值