MySQL面试题

MySQL面试题

如何设计一个关系型数据库?

首先划分为两大部分,一个存储部分,类似文件系统将数据持久化到硬盘上, 另一个是程序实例部分,创建模块: 存储管理,缓存机制,SQL解析,日志管理,权限划分,容灾机制**,索引管理,锁模块**。

数据库的三范式是什么?

  • 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
  • 第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
  • 第三范式:任何非主属性不依赖于其它非主属性。

mysql执行流程

说一下 ACID 是什么?

Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。

Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。

Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。

Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

char 和 varchar 的区别是什么?

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

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

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

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

说一下数据库的事务隔离?

可用的配置值:READ-UNCOMMITTED、READ-COMMITTED、REPEATABLE-READ、SERIALIZABLE。

READ-UNCOMMITTED:未提交读,最低隔离级别、事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。

READ-COMMITTED:提交读,一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。

REPEATABLE-READ:可重复读,mysql默认级别,保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据(会造成幻读)。

SERIALIZABLE:序列化,代价最高最可靠的隔离级别,该隔离级别能防止脏读、不可重复读、幻读。

补充:

脏读 :表示一个事务能够读取另一个事务中还未提交的数据。比如,某个事务尝试插入记录 A,此时该事务还未提交,然后另一个事务尝试读取到了记录 A。

不可重复读 :是指在一个事务内,多次读同一数据数据发生了变化。

幻读 :指同一个事务内多次查询返回的结果集不一样。比如同一个事务 A 第一次查询时候有 n 条记录,但是第二次同等条件下查询却有 n+1 条记录,这就好像产生了幻觉。发生幻读的原因也是另外一个事务新增或者删除或者修改了第一个事务结果集里面的数据,同一个记录的数据内容被修改了,所有数据行的记录就变多或者变少了。

MySQL逻辑架构和执行流程?

MySQL面试题

 

说一下 mysql 常用的引擎?

InnoDB 引擎:InnoDB 引擎提供了对数据库 acid 事务的支持,并且还提供了行级锁和外键的约束,它的设计的目标就是处理大数据容量的数据库系统。MySQL 运行的时候,InnoDB 会在内存中建立缓冲池,用于缓冲数据和索引。但是该引擎是不支持全文搜索,同时启动也比较的慢,它是不会保存表的行数的,所以当进行 select count(*) from table 指令的时候,需要进行扫描全表。由于锁的粒度小,写操作是不会锁定全表的,所以在并发度较高的场景下使用会提升效率的。

MyISAM 引擎:MySQL 的默认引擎,但不提供事务的支持,也不支持行级锁和外键。因此当执行插入和更新语句时,即执行写操作的时候需要锁定这个表,所以会导致效率会降低。不过和 InnoDB 不同的是,MyIASM 引擎是保存了表的行数,于是当进行 select count(*) from table 语句时,可以直接的读取已经保存的值而不需要进行扫描全表。所以,如果表的读操作远远多于写操作时,并且不需要事务的支持的,可以将 MyIASM 作为数据库引擎的首选。

Myisam和InnoDB的区别

  • 是否支持行级锁 : MyISAM 只有表级锁(table-level locking),而InnoDB 支持行级锁(row-level locking)和表级锁,默认为行级锁,适合高并发操作。
  • 是否支持外键: MyISAM不支持,而InnoDB支持
  • 是否支持事务:MyISAM不支持,而InnoDB支持
  • 缓存:MyISAM只缓存索引,InnoDB缓存索引和真实数据,所以对内存要求高
  • 崩溃恢复:MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。

mysql 索引是怎么实现的?

索引是满足某种特定查找算法的数据结构,而这些数据结构会以某种方式指向数据,从而实现高效查找数据。 MySQL 中的索引,不同的数据引擎实现有所不同,但目前主流的数据库引擎的索引都是 B+ 树实现的 。

B树和B+树的概念和区别

1)B-树的关键字和记录是放在一起的,叶子节点可以看作外部节点,不包含任何信息;B+树的非叶子节点中只有关键字和指向下一个节点的索引,记录只放在叶子节点中。 2)在B-树中,越靠近根节点的记录查找时间越快,只要找到关键字即可确定记录的存在;而B+树中每个记录的查找时间基本是一样的,都需要从根节点走到叶子节点,而且在叶子节点中还要再比较关键字。从这个角度看B-树的性能好像要比B+树好,而在实际应用中却是B+树的性能要好些

原因:

  • 因为B+树的非叶子节点不存放实际的数据,这样每个节点可容纳的元素个数比B-树多,树高比B-树小,这样带来的好处是减少磁盘访问次数。尽管B+树找到一个记录所需的比较次数要比B-树多,但是一次磁盘访问的时间相当于成百上千次内存比较的时间,因此实际中B+树的性能可能还会好些。
  • B+树的叶子节点使用指针连接在一起,方便顺序遍历(例如查看一个目录下的所有文件,一个表中的所有记录等)。
  • B+树的查询效率更加稳定,每次查询的效率一样。

什么样的信息能成为索引

主键,唯一键,普通键都可,只要能让数据有一定区分性的字段。

说一下乐观锁和悲观锁?

乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。

悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。

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

mysql 问题排查都有哪些手段?

  • 使用 show processlist 命令查看当前所有连接信息。
  • 使用 explain 命令查询 SQL 语句执行计划。
  • 开启慢查询日志,查看慢查询的 SQL。

性能分析的重点字段

type

type显示的是访问类型 system>const>eq_ref>ref>range>index>ALL,一般来说,得保证查询至少达到range级别,最好能达到ref。

三个较差情况: 1.range: 只检索给定范围的行,使用一个索引来选择行。key 列显示使用了哪个索引 一般就是在你的where语句中出现了between、<、>、in等的查询 这种范围扫描索引扫描比全表扫描要好,因为它只需要开始于索引的某一点,而结束语另一点,不用扫描全部索引。

2.index: 出现index是sql使用了索引但是没用通过索引进行过滤,一般是使用了覆盖索引或者是利用索引进行了排序分组 ,一般是where后面没有优化索引

3.all(最差): Full Table Scan,将遍历全表以找到匹配的行

备注:一般来说,得保证查询至少达到range级别,最好能达到ref。

Extra

包含不适合在其他列中显示但十分重要的额外信息,主要用来检测 order by,group by或者关联查询是否使用了索引。 有以下几种情况: 1.Using filesort 2.Using temporary 3.using join buffer都是很差的是使用方式。要建立索引。 4.impossible where:不可能出现的情况,一般为 逻辑出现错误。 5.USING index: 利用索引进行了排序或分组, 表示相应的select操作中使用了覆盖索引(Covering Index),避免访问了表的数据行,效率不错! 如果同时出现using where,表明索引被用来执行索引键值的查找; 如果没有同时出现using where,表明索引只是用来读取数据而非利用索引执行查找。

如何做 mysql 的性能优化?

  • 避免使用 select *,列出需要查询的字段;
  • 使用 LIMIT 语句来限制返回的数据;
  • 垂直分割分表;
  • 选择正确的存储引擎;
  • 为搜索字段创建索引;
  • 创建多列索引时遵循最佳左前缀法则 ;
  • 不在索引列上和where后做任何操作(计算、函数、(自动or手动)类型转换),会导致索引失效而转向全表扫描;
  • like以通配符开头(’%abc…’)mysql索引失效会变成全表扫描的操作 ;
  • mysql 在使用不等于(!= 或者<>)的时候无法使用索引会导致全表扫描;
  • is not null 也无法使用索引,但是is null是可以使用索引的 ;