MySQL

EmiyaCC 于 2021-06-24 发布

数据库的三范式是什么?

一张自增表里面总共有 17 条数据,删除了最后 2 条数据,重启 MySQL 数据库,又插入了一条数据,此时 id 是几?

InnoDB 表只会把自增主键的最大 id 记录在内存中,所以重启之后会导致最大 id 丢失。

char 和 varchar 的区别是什么?

char(n) :固定长度类型,比如订阅 char(10),当你输入”abc”三个字符的时候,它们占的空间还是 10 个字节,其他 7 个是空字节。

char 优点:效率高;缺点:占用空间;适用场景:存储密码的 md5 值,固定长度的,使用 char 非常合适。

varchar(n) :可变长度,存储的值是每个值占用的字节再加上一个用来记录其长度的字节的长度。

所以,从空间上考虑 varcahr 比较合适;从效率上考虑 char 比较合适,二者使用需要权衡。

float 和 double 的区别是什么?

MySQL 的内连接、左连接、右连接有什么区别?

内连接关键字:inner join;左连接:left join;右连接:right join。

内连接是把匹配的关联数据显示出来;左连接是左边的表全部显示出来,右边的表显示出符合条件的数据;右连接正好相反。

左连接 ,右连接,内连接和全外连接的4者区别

MySQL的存储引擎?

InnoDB: 支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。

MyISAM: 插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。

MEMORY: 所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

注意:同一个数据库也可以使用多种存储引擎的表。如果一个表要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎。

MySQL - 常见的三种存储引擎

Mysql各种存储引擎对比总结

MySQL 三大日志-binlog、redo log和undo log

索引的基本原理

索引的优缺点

什么时候不要使用索引

  1. 经常增删改的列不要建立索引;
  2. 有大量重复的列不建立索引;
  3. 表记录太少不要建立索引。

MySQL 索引有哪些

按数据结构分类可分为:B+tree索引、Hash索引、Full-text索引。 按物理存储分类可分为:聚簇索引、二级索引(辅助索引)。

索引类型:

MySQL的索引失效

索引失效

MySQL 聚簇索引和非聚簇索引区别

都是 B+ 树结构

区别:

聚簇索引优点:

  1. 查询通过聚簇索引可以直接获取数据,相比非聚簇索引需要二次查询(非覆盖索引的情况下)效率更高
  2. 聚簇索引对于范围查询的效率更高,因为数据是按照大小排列的
  3. 聚簇索引适合排序场合,非聚簇索引不适合

聚簇索引缺点:

  1. 维护索引费用昂贵
  2. 表使用 UUID(随机 ID)作为主键,使数据存储稀疏,这会出现聚簇索引有可能比全表扫描更慢,索引建议使用 int 的 auto_increment 作为主键
  3. 如果主键比较大,辅助索引也会变得更大,因为辅助索引的叶子存储的是主键值;过长的主键值会导致叶子节点占用更多的物理空间

MySQL 索引的数据结构

索引的数据结构和具体存储引擎的实现有关,再 MySql 中使用较多的是 Hash 索引和 B+ 树索引。InnoDB存储引擎默认索引实现是 B+ 树索引。对于 Hash 索引来说,底层的数据结构就是哈希表,因此在绝大多数需求为单条记录查询的时候,可以选择 Hash 索引,查询性能最快;其余大部分场景,建议选择 B+ 树索引

MySQL 索引是怎么实现的?

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。

具体来说 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的,B+ 树的搜索效率,可以到达二分法的性能,找到数据区域之后就找到了完整的数据结构了,所有索引的性能也是更好的。

补充:

怎么验证 MySQL 的索引是否满足需求?

使用 explain 查看 SQL 是如何执行查询语句的,从而分析你的索引是否满足需求。

explain 语法:explain select * from table where type=1。

explain结果每个字段的含义说明

慢SQL优化实战笔记

说一下 MySQL 常用的引擎,有什么区别?

  1. InnoDB 引擎提供了行级锁,它的设计的目标就是处理大数据容量的数据库系统;MyISAM 不支持行级锁,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。
  2. InnoDB支持事务,MyISAM不支持,对于InnoDB每一条SQL语言都默认封装成事务,自动提交,这样会影响速度,所以最好把多条SQL语言放在begin和commit之间,组成一个事务;
  3. InnoDB支持外键,而MyISAM不支持。对一个包含外键的InnoDB表转为MYISAM会失败;
  4. InnoDB是聚集索引,数据文件是和索引绑在一起的,必须要有主键,通过主键索引效率很高。但是辅助索引需要两次查询,先查询到主键,然后再通过主键查询到数据。因此,主键不应该过大,因为主键太大,其他索引也都会很大。而MyISAM是非聚集索引,数据文件是分离的,索引保存的是数据文件的指针。主键索引和辅助索引是独立的。
  5. InnoDB不保存表的具体行数,执行select count(*) from table时需要全表扫描。而MyISAM用一个变量保存了整个表的行数,执行上述语句时只需要读出该变量即可,速度很快;
  6. Innodb不支持全文索引,而MyISAM支持全文索引,查询效率上MyISAM要高;

MySQL 事务隔离级别,默认隔离级别,为什么这么选

四个隔离级别:

默认隔离级别:

InnoDB 存储引擎在 REPEATABLE-READ(可重读),事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如SQL Server) 是不同的。

所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的 SERIALIZABLE(可串行化) 隔离级别。

为什么会默认可重复读:

考虑 MySQL 的主从同步,隔离级别设为可重复读(Repeatable Read),在该隔离级别下引入间隙锁,实现了写入 Binlog 的语句串行化。解决了主从不一致的问题。

脏读、不可重复读、幻读

快速理解脏读、不可重复读、幻读和MVCC - 云+社区- 腾讯云

数据库的封锁协议

说一下 ACID 是什么?

说一下 MySQL 的行锁和表锁?

MyISAM 只支持表锁,InnoDB 支持表锁和行锁,默认为行锁。

说一下乐观锁和悲观锁?

数据库的乐观锁需要自己实现,在表里面添加一个 version 字段,每次修改成功值加 1,这样每次修改的时候先对比一下,自己拥有的 version 和数据库现在的 version 是否一致,如果不一致就不修改,这样就实现了乐观锁。

怎样尽量避免死锁的出现

  1. 设置获取锁的超时时间,至少能保证最差情况下,可以退出程序,不至于一直等待导致死锁;
  2. 设置按照同一顺序访问资源,类似于串行执行;
  3. 避免事务中的用户交叉;
  4. 保持事务简短并在一个批处理中;
  5. 使用低隔离级别;
  6. 使用绑定链接。

什么是 MVCC?

英文全称为Multi-Version Concurrency Control,乐观锁为理论基础的MVCC(多版本并发控制),MVCC的实现没有固定的规范。每个数据库都会有不同的实现方式。

MVCC 手段只适用于 MySQL 隔离级别中的读已提交和可重复读,而读未提交由于存在脏读,即能读到未提交事务的数据行,所以不适用 MVCC。原因是 MVCC 的创建版本和删除版本只要在事务提交后才会产生。串行化由于是会对所涉及到的表加锁,并非行锁,自然也就不存在行的版本控制问题。

通过以上总结,可知,MVCC 主要作用于事务性的,有行锁控制的数据库模型。

快速理解脏读、不可重复读、幻读和MVCC - 云+社区- 腾讯云

MySQL 主从同步原理

如何做 MySQL 的性能优化?

MySQL索引优化

大表如何优化

分库分表之后,id 主键如何处理

因为要是分成多个表之后,我们需要一个全局唯一的 id 来支持。生成全局 id 有下面这几种方式:

  1. UUID:不适合作为主键,因为太长了,并且无序不可读,查询效率低。比较适合用于生成唯一的名字的标示比如文件的名字。
  2. 数据库自增 id : 两台数据库分别设置不同步长,生成不重复ID的策略来实现高可用。这种方式生成的 id 有序,但是需要独立部署数据库实例,成本高,还会有性能瓶颈。
  3. 利用 redis 生成 id : 性能比较好,灵活方便,不依赖于数据库。但是,引入了新的组件造成系统更加复杂,可用性降低,编码更加复杂,增加了系统成本。
  4. Twitter的snowflake算法 :Github 地址:https://github.com/twitter-archive/snowflake
  5. 美团的Leaf分布式ID生成系统 :Leaf 是美团开源的分布式ID生成器,能保证全局唯一性、趋势递增、单调递增、信息安全,里面也提到了几种分布式方案的对比,但也需要依赖关系数据库、Zookeeper等中间件。感觉还不错。美团技术团队的一篇文章:Leaf——美团点评分布式ID生成系统

MySQL 中一条查询 SQL 是如何执行的

  1. 取得链接,使用使用到 MySQL 中的连接器。
  2. 分析器,分为词法分析和语法分析。此阶段只是做一些 SQL 解析,语法校验。所以一般语法错误在此阶段。
  3. 优化器,是在表里有多个索引的时候,决定使用哪个索引;或者一个语句中存在多表关联的时候(join),决定各个表的连接顺序。
  4. 执行器,通过分析器让 SQL 知道你要干啥,通过优化器知道该怎么做,于是开始执行语句。执行语句的时候还要判断是否具备此权限,没有权限就直接返回提示没有权限的错误;有权限则打开表,根据表的引擎定义,去使用这个引擎提供的接口,获取这个表的第一行,判断 id 是都等于 1。如果是,直接返回;如果不是继续调用引擎接口去下一行,重复相同的判断,直到取到这个表的最后一行,最后返回。

Reference: