面试-MySql

164. 数据库的三范式是什么?
165. 一张自增表里面总共有 7 条数据,删除了最后 2 条数据,重启 mysql 数据库,又插入了一条数据,此时 id 是几?
166. 如何获取当前数据库版本?
167. 说一下 ACID 是什么?
168. char 和 varchar 的区别是什么?
169. float 和 double 的区别是什么?
170. mysql 的内连接、左连接、右连接有什么区别?
171. mysql 索引是怎么实现的?
172. 怎么验证 mysql 的索引是否满足需求?
173. 说一下数据库的事务隔离?
174. 说一下 mysql 常用的引擎?
175. 说一下 mysql 的行锁和表锁?
176. 说一下乐观锁和悲观锁?
177. mysql 问题排查都有哪些手段?
178. 如何做 mysql 的性能优化?

MySql

164. 数据库的三范式是什么?

范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”

  • 第一范式:强调的是列的原子性,即数据库表的每一列都是不可分割的原子数据项。
    两列的属性相近或相似或一样,尽量合并属性一样的列,确保不产生冗余数据。
  • 第二范式:要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性。
    每一行的数据只能与其中一列相关,即一行数据只做一件事。只要数据列中出现数据重复,就要把表拆分开来。
    一个人同时订几个房间,就会出现一个订单号多条数据,这样子联系人都是重复的,就会造成数据冗余。我们应该把他拆开来
  • 第三范式:任何非主属性不依赖于其它非主属性。

    数据不能存在传递关系,即每个属性都跟主键有直接关系而不是间接关系。
    比如这样一个表结构Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)
    这样的表结构,我们应该拆开来,如下。
    (学号,姓名,年龄,所在院校)--(所在院校,院校地址,院校电话)

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

  • 表类型如果是 MyISAM ,那 id 就是 8。
  • 表类型如果是 InnoDB,那 id 就是 5。

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

166. 如何获取当前数据库版本?

使用 select version() 获取当前 MySQL 数据库版本。

167. 说一下 ACID 是什么?

  • Atomicity(原子性):一个事务(transaction)中的所有操作,或者全部完成,或者全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被恢复(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。即,事务不可分割、不可约简。
  • Consistency(一致性):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设约束、触发器、级联回滚等。
  • Isolation(隔离性):数据库允许多个并发事务同时对其数据进行读写和修改的能力,并发执行的事务彼此无法看到对方的中间状态,多个并发事务之间要相互隔离,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。一般通过悲观或者乐观锁实现
    事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
  • Durability(持久性):事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

168. char 和 varchar 的区别是什么?

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

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

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

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

169. float 和 double 的区别是什么?

  • float 最多可以存储 8 位的十进制数,并在内存中占 4 字节。有效数位是7位(因为有正负,所以不是8位)
  • double 最可可以存储 16 位的十进制数,并在内存中占 8 字节。有效数位是16位

170. mysql 的内连接、左连接、右连接有什么区别?

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

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

171. mysql 索引是怎么实现的?

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

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

172. 怎么验证 mysql 的索引是否满足需求?

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

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

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

MySQL 的事务隔离是在 MySQL. ini 配置文件里添加的,在文件的最后添加:transaction-isolation = REPEATABLE-READ

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

  • READ-UNCOMMITTED:读未提交,最低隔离级别,写事务会禁止其他写事务,但允许其他事务读此行数据。事务未提交前,就可被其他事务读取(会出现幻读、脏读、不可重复读)。
  • READ-COMMITTED:读已提交,读事务允许其他事务继续访问该行数据,但是未提交的写事务将会禁止其他事务访问该行。一个事务提交后才能被其他事务读取到(会造成幻读、不可重复读)。
  • REPEATABLE-READ:可重复读,默认级别,读事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务。可重复读可以解决不可重复读问题。不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。(会出现幻读)。
  • SERIALIZABLE:序列化,代价最高最可靠的隔离级别,提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。该隔离级别能防止脏读、不可重复读、幻读。

脏读 :表示一个事务能够读取另一个事务中还未提交的数据。

不可重复读 :一个事务内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。

幻读 :指同一个事务内多次查询返回的结果集不一样。后一次查询看到了前一次查询没有看到的行数据,发生幻读的原因也是由于在查询间隔,被另一个事务修改并提交了

不可重复读和幻读这两者有些相似,所不同的是不可重复读针对的是一条数据,而幻读针对的是一个数据整体,不可重复读重点在于update和delete,而幻读的重点在于insert。避免不可重复读需要锁行(某一行在select操作时,不允许update与delete)就行,避免幻读则需要锁表。

174. 说一下 mysql 常用的引擎?

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

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

175. 说一下 mysql 的行锁和表锁?

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

  • 表级锁:开销小,加锁快,不会出现死锁。锁定粒度大,发生锁冲突的概率最高,并发量最低。
  • 行级锁:开销大,加锁慢,会出现死锁。锁力度小,发生锁冲突的概率小,并发度最高。

176. 说一下乐观锁和悲观锁?

  • 乐观锁:每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。
  • 悲观锁:每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻止,直到这个锁被释放。

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

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

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

178. 如何做 mysql 的性能优化?

  • 为搜索字段创建索引。
  • 避免使用 select *,列出需要查询的字段。
  • 垂直分割分表。
  • 选择正确的存储引擎。

你可能感兴趣的