13.简述数据库的隔离级别?
读未提交:指一个事务读取另一个事务未提交的修改。,会发生脏读、不可重复读、幻读。 读提交:指只能读到已经提交的内容。会发生不可重复读和幻读。是SQL Server和Oracle的默认隔离级别。 可重复读:指当数据被读取时,不可进行update操作,保证多次读取的记录是相同的,解决了不可重复读的问题。但幻读是insert导致,不会避免。可重复读是MySQL的默认隔离级别。 可串行化读:这是数据库最高的隔离级别,这种级别下,事务“串行化顺序执行”,也就是一个一个排队执行。这种级别下,“脏读”、“不可重复读”、“幻读”都可以被避免,但是执行效率奇差,性能开销也最大,所以基本没人会用。
14.简述MySQL可以从哪些方面做到性能优化?
为搜索字段创建索引。 避免使用 Select *,列出需要查询的字段。 垂直分割分表,水平分割是分割记录,以一条记录/行为单位。垂直分割则是以列为单位,将列分割出去。 选择正确的搜索引擎。 实现数据库的主从同步,实现读写分离。 添加合适的缓存机制,维护代价高。 对冷热数据进行均分,减少单个库的压力,使整体性能达到更优。
15.简ySQL为什么需要事务回滚机制?
在MySQL中事务回滚通过日志完成,所有事务进行的修改都会先记录到回滚日志中,然后再对数据库中的对应行进行写入。当事务被提交后就无法回滚了。
回滚日志的作用:
能够在发生错误或用户执行rollback时提供回滚的相关信息。 在整个系统发生崩溃、数据库进程直接被杀死后,当用户再次启动数据库进程时,还能够立刻通过查询回滚日志将之前未完成的事务进行回滚,这也就需要回滚日志必须先于数据持久化到磁盘上,是我们需要先写日志后写数据库的主要原因。
16.简述MySQL引擎InnoDB和MyISAM的区别?
InnoDB:
是MySQL默认的事务型存储引擎,只有当需要它不支持的特性时,才会考虑使用其它的存储引擎。 实现了四个标准的隔离级别,其中默认为可重复读,在可重复读的隔离级别下,通过MVCC(多版本并发控制协议)+ 间隙锁(Next-key Locking)防止幻读。 主索引为聚簇索引,在索引中保存数据,从而避免直接读取磁盘,因此对查询性能有很大的提升。 支持真正的在线热备份。其它存储引擎不支持在线热备份。 支持行级锁,通过给索引项加锁来实现,即只有通过索引条件检索数据,才会使用行级锁,否则使用表锁。 InnoDB不会对表中行的总量进行预先统计,每次count需要遍历计算。
MyISAM:
设计简单,数据以紧密格式存储。对于只读数据,或者表比较小、可以容忍修复操作,则依然可以使用它。 提供了大量的特性,包括压缩表、空间数据索引等。 不支持事务。 不支持行级锁,只能对整张表加锁,读取时会对需要读到的所有表加共享锁,写入时则对表加排它锁。 会实时保存数据库表中的总行数,计算快。
总结:
事务:MyISAM不支持,InnoDB支持。 锁级别: MyISAM 表级锁,InnoDB 行级锁及外键约束。 MyISAM存储表的总行数;InnoDB不存储总行数。 MyISAM采用非聚集索引,B+树叶子存储指向数据文件的指针。InnoDB主键索引采用聚集索引,B+树叶子存储数据。 崩溃恢复: MyISAM 崩溃后发生损坏的概率比 InnoDB 高很多,而且恢复的速度也更慢。
使用场景:
MyISAM适合:插入不频繁,查询非常频繁,如果执行大量的SELECT,MyISAM是更好的选择,没有事务。 InnoDB适合:可靠性要求比较高,或者要求事务; 表更新和查询都相当的频繁, 大量的INSERT或UPDATE。
17.数据库分库分表的原因?
分库分表的目的在于减少数据库单库单表的负担,提高查询性能,缩短查询时间。 分库分表分别水平切分和垂直切分。 垂直切分:分为垂直分库和垂直分表,其中垂直分库是指根据业务的耦合度,将关联度较低的不同表存储于不同的库中,类似于大系统拆分为小系统;垂直分表是指基于数据库表中的列,将不常用的列进行划分成新表,可以使单个表中的数据量变少减少跨页,使得单个页中字段更多,使内存能够加载更多的数据,提高命中率,减少磁盘IO,提高性能。 水平切分:水平切分是根据表内数据内在的逻辑关系,将同一个表按不同的条件分散到多个数据库或多个表中,每个表中只包含一部分数据,从而使得单个表的数据量变小,达到分布式的效果。但只是库内分表,仅仅是解决了单表数据过大的问题,并没有把单表的数据分散到不同的物理机上,因此并不能减轻 MySQL 服务器的压力,仍然存在同一个物理机上的资源竞争和瓶颈,包括 CPU、内存、磁盘 IO、网络带宽等。 使用哪种方式分库分表需要依据情况而定,比如数据库是因为表太多而造成海量数据,并且项目的各项业务逻辑划分清晰、低耦合,那么规则简单明了、容易实施的垂直切分必是首选。而如果数据库中的表并不多,但单表的数据量很大、或数据热度很高,这种情况之下就应该选择水平切分,水平切分比垂直切分要复杂一些,它将原本逻辑上属于一体的数据进行了物理分割,除了在分割时要对分割的粒度做好评估,考虑数据平均和负载平均,后期也将对项目人员及应用程序产生额外的数据管理负担。
18.简述什么是覆盖索引?
如果一个索引包含所有需要查询的字段的值,我们就称 之为“覆盖索引”。 对于InnoDB存储引擎来说,如果不是主键索引,那么辅助索引的叶子节点存储的是主键+辅助索引的列值,然后还需要进行回表操作。 这样的话,会降低查询速度,因此,若使用辅助索引查询时,若查询得到的值和需要查询的结果列值时对应的(或者覆盖),则可以一直接使用其结果,不需要进行回表操作。
19.简述三大范式的特点?
第一范式:指数据库表中的每一列都是不可分割的基本数据项,同一列中不能有多个值相同,即无重复的列。 第二范式:满足第一范式,还要求数据库表中的每个实例或行必须被唯一标识,满足实体的属性完全依赖于主关键字。 第三范式:满足第二范式,还要求数据库表中不包含其他表中的非主关键字信息,即两个表中不存在相同的非主关键字信息,否则会造成数据冗余。
20.简述聚簇索引与非聚簇索引(辅助)的区别?
聚簇索引的叶子节点存放的是主键值和数据行,支持覆盖索引;非聚簇索引的叶子节点存放的是主键值或指向数据行的指针。 聚集索引就是以主键创建的索引,非聚集索引就是以非主键创建的索引。 由于节子节点(数据页)只能按照一颗B+树排序,故一张表只能有一个聚簇索引。辅助索引的存在不影响聚簇索引中数据的组织,所以一张表可以有多个辅助索引。
21.简述事务的四大特性?
原子性:指事务包含的所有操作要么全部成功,要么全部失败回滚,因此事务的操作如果成功就必须完全应用到数据库,如果操作失败则不能对数据库有任何影响。 一致性:指事务开始前和结束后,数据库的完整性约束没有被破坏。 隔离性:指当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。 持久性:指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。
22.简述创建索引的注意事项?
非空字段:索引字段不能有NULL,如果有NULL值将不会包含在索引中。 索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操作获取的数据越大效率越高。 唯一、不为空、经常被查询的字段 的字段适合建索引。 取值离散大的字段:(变量各个取值之间的差异程度)的列放到联合索引的前面,可以通过count()函数查看字段的差异值,返回值越大说明字段的唯一值越多字段的离散程度高。 限制创建索引的数量:对于存在大量更新操作的表,索引一般不超过3个。
23.为什么索引的数量不能太多?
当对表中的数据进行增加、删除、修改时,同时需要动态维护索引,降低了整体的维护速度。 索引需要占据物理空间,如果要建立聚簇索引,那么需要的空间就会更大,因为会将数据存储于叶子节点。 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加。
24.简述数据库的行级锁与表锁?
表锁:
不会出现死锁,发生锁的冲突几率高,并发性低。 存储引擎在进行SQL数据读写请求前,会对涉及到的表进行加锁。 其中锁分为共享读锁和独占写锁:读锁会阻塞写,写锁会阻塞读和写。
行级锁:
会出现死锁,发生锁的冲突几率低,并发性高。 InnoDB引擎支持行锁,与Oracle不同,MySQL的行锁是通过索引加载的,也就是说,行锁是加在索引响应的行上的,要是对应的SQL语句没有走索引,则会全表扫描,行锁则无法实现,取而代之的是表锁,此时其它事务无法对当前表进行更新或插入操作。
行级锁注意事项:
行级锁必须有索引才能实现,否则会自动锁全表,那就不是行锁了。 两个事务不能锁同一个索引。 insert,delete,update在事务中都会自动默认加上排它锁。
行锁的适用场景:
避免不可重复读的场景。
25.简述为什么MySQL索引使用B+树而不用hash表和B树?
利用Hash需要把数据全部加载到内存中,如果数据量大,是一件很消耗内存的事,而采用B+树,是基于按照节点分段加载,由此减少内存消耗。 和业务场景有段,对于唯一查找(查找一个值),Hash确实更快,但数据库中经常查询多条数据,这时候由于B+数据的有序性,与叶子节点又有链表相连,他的查询效率会比Hash快的多。 b+树的非叶子节点不保存数据,只保存子树的临界值(最大或者最小),所以同样大小的节点,b+树相对于b树能够有更多的分支,使得这棵树更加矮胖,查询时做的IO操作次数也更少。
26.简述B树的结构及特点?
对于一个M阶的B树有以下特征:
第一任何非叶子节点最多只有M个儿子,且M > 2; 根节点的儿子数量范围为[2,M]; 除根节点 以外的非叶子节点的儿子数量为[M/2,M],向上取整,M/2是由于当某个节点达到M个节点信息时,会进行拆分为两个叶子节点。 非叶子节点的关键字数量 = 叶子数量 - 1; 所有的叶子节点位于同一层; k个关键字把节点拆成k+1段,分别指向k+1个儿子,同时满足查找树的大小关系; 每个节点除了存储索引外还保存该索引对应数据的地址;
27.简述B+树的结构及特点?
对于一个M阶的B树有以下特征:
有k个子树的中间节点包含有k个元素(B树中是k-1个元素),每个元素不保存数据,只用来索引,所有数据都保存在叶子节点。 所有的叶子结点中包含了全部元素的信息,及指向含这些元素记录的指针,且叶子结点本身依关键字的大小自小而大顺序链接,形成一个有序的链表。 所有的中间节点元素都同时存在于子节点,在子节点元素中是最大(或最小)元素。 由于每个节点只存索引,因此每个页存储的数据变多,可减少IO次数。
28.数据库如何保证事务的ACID特性?
原子性:使用innodb的undo log(回滚日志),undo log记录了回滚需要的信息,当事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。 隔离性: 使用悲观锁和乐观锁对事务处理。 持久性:使用innodb的redo log(重写日志), 记录的是数据页的物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置);当做数据修改的时候,不仅在内存中操作,还会在redo log中记录这次操作。当事务提交的时候,会将redo log日志进行刷盘(redo log一部分在内存中,一部分在磁盘上)。当数据库宕机重启的时候,会将redo log中的内容恢复到数据库中,再根据undo log和binlog内容决定回滚数据还是提交数据。 一致性:通过原子性、隔离性、持久性来保证一致性。
29.简述使用redo log的好处?
redo log体积小,毕竟只记录了哪一页修改了啥,因此体积小,刷盘快。 redo log是一直往末尾进行追加,属于顺序IO。效率显然比随机IO来的快。
30.如何解决数据库高并发问题?
在web服务框架中加入缓存。在服务器与数据库层之间加入缓存层,将高频访问的数据存入缓存中,减少数据库的读取负担。 增加数据库索引,进而提高查询速度。(不过索引太多会导致速度变慢,并且数据库的写入会导致索引的更新,也会导致速度变慢) 主从读写分离,让主服务器负责写,从服务器负责读。 将数据库进行拆分,使得数据库的表尽可能小,提高查询的速度。 使用分布式架构,分散计算压力。
31.简述联合索引的最左匹配原则?
MySQL建立联合索引时遵循最左匹配原则,即最左优先,在检索数据时从联合索引的最左边开始匹配。 对于联合索引而言构造B+树,会依次从左往右按顺序比较进行键值插入,遇到范围查找就会停止,剩下的字段就会失效无法使用索引。
32.简述SQL语句的优先级顺序?
from:需要从哪个数据表检索数据 join:联合多表查询返回记录时,并生成一张临时表 on:在生成临时表时使用的条件 where:过滤表中数据的条件 group by:如何将上面过滤出的数据分组 having:对上面已经分组的数据进行过滤的条件 select:查看结果集中的哪个列,或列的计算结果 order by :按照什么样的顺序来查看返回的数据
33.简述索引失效的情况?
like 以%开头,索引无效;当like前缀没有%,后缀有%时,索引有效。 or语句前后没有同时使用索引。当or左右查询字段只有一个是索引,该索引失效,只有当or左右查询字段均为索引时,才会生效。 组合索引,不是使用第一列索引,索引失效。 数据类型出现隐式转化。如varchar不加单引号的话可能会自动转换为int型,使索引无效,产生全表扫描。 在索引列上使用 IS NULL 或 IS NOT NULL操作。 在索引字段上使用not,,!=。不等于操作符是永远不会用到索引的,因此对它的处理只会产生全表扫描。 优化方法: key0 改为 key>0 or key<0。 对索引字段进行计算操作、字段上使用函数。 当全表扫描速度比索引速度快时,mysql会使用全表扫描,此时索引失效。
如何检查索引是否失效:
可以使用explain命令加在要分析的sql语句前面,在执行结果中查看key这一列的值,如果为NULL,说明没有使用索引。
34.简述什么情况下不应该创建索引?
对于那些在查询中很少使用或者参考的列不应该创建索引。这是因为,既然这些列很少使用到,因此有索引或者无索引,并不能提高查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。 对于那些只有很少数据值的列也不应该增加索引。这是因为,由于这些列的取值很少,例如人事表的性别列,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。 对于那些定义为text, image和bit数据类型的列不应该增加索引。这是因为,这些列的数据量要么相当大,要么取值很少。 当修改性能远远大于检索性能时,不应该创建索引。这是因为,修改性能和检索性能是互相矛盾的。