MySQL是一种关系型数据库管理系统,可以通过SQL管理数据库;定义和操作数据,维护数据的完整性和安全性。
1. 简述在MySQL数据库中引擎MyISAM和InnoDB的区别?
MyISAM和InnoDB都是MySQL数据库的存储引擎,InnoDB在MyISAM的基础上强化参考完整性与并发违规处理机制,二者的主要区别在于:
- 存储结构方面:MyISAM每个MyISAM在磁盘上存储成三个文件.frm文件存储表定义、数据文件的扩展名为.MYD、索引文件的扩展名是.MYI;InnoDB所有的表都保存在同一个数据文件中,表的大小只受限于操作系统文件的大小,一般为2GB。
- 存储空间方面:MyISAM可被压缩,存储空间较小。支持三种不同的存储格式:静态表、动态表、压缩表;InnoDB需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。
- 事务支持方面:MyISAM强调的是性能,每次查询具有原子性,其执行数度比InnoDB类型更快,但是不提供事务支持;InnoDB提供事务支持事务。
- 表锁差异方面:MyISAM只支持表级锁;InnoDB支持事务和行级锁。
- 表主键:MyISAM允许没有任何索引和主键的表存在,索引都是保存行的地址。InnoDB如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键。
- 增删改查操作方面:如果执行大量的SELECT,MyISAM是更好的选择。如果执行大量的INSERT或UPDATE,出于性能方面的考虑,应该使用InnoDB表。
MyISAM适合:(1)做很多count 的计算;(2)插入不频繁,查询非常频繁;(3)没有事务。
InnoDB适合:(1)可靠性要求比较高,或者要求事务,比如说操作订单表、账户表;(2)表更新和查询都相当的频繁,并且行锁定的机会比较大的情况。
MySQL索引相关面试题
2、MySQL中索引的基本原理
索引可以帮助MySQL高效获取数据的数据结构,索引能够提高数据检索的效率,降低数据库的IO成本,降低CPU的消耗。频繁的查询操作、排序操作需要建立索引;而频繁更新的字段不太需要建立索引。
索引的基本原理:
1、把创建了索引的内容进行排序
2、将排序的结果生成一个倒排表(例如按照hash值排序、按照B+树排序)
3、再倒排表上拼上数据地址链
4、在查询的时候,首先拿到倒排表内容,再取出数据地址链,从而拿到对应的数据。
索引可分为:单值索引、唯一索引、复合索引
索引底层数据结构一般为 哈希表、二叉树、平衡二叉树、红黑树、B树、B+树。
3、MySQL为什么采用B+树作为索引的数据结构?
MySQL的数据是存储在磁盘文件中的,查询处理数据时,需要先把磁盘中的数据加载到内存中,磁盘IO 操作非常耗时,所以我们优化的重点就是尽量减少磁盘 IO 操作。访问二叉树的每个节点就会发生一次IO,如果想要减少磁盘IO操作,就需要尽量降低树的高度。
什么是B树:
- B树的节点中存储着多个元素,每个内节点有多个分叉。
- 节点中的元素包含键值和数据,节点中的键值从大到小排列。也就是说,在所有的节点都储存数据。
- 父节点当中的元素不会出现在子节点中。
- 所有的叶子结点都位于同一层,叶节点具有相同的深度,叶节点之间没有指针连接。
什么是B+树:
B+树,作为B树的升级版,在B树基础上,MySQL在B树的基础上继续改造,使用B+树构建索引。B+树和B树最主要的区别在于非叶子节点是否存储数据的问题,B+树中非叶子节点不存储数据,只存键值。且B+树同层级的节点间依靠指针相互连接。
B+树的最底层叶子节点包含了所有的索引项。从图上可以看到,B+树在查找数据的时候,由于数据都存放在最底层的叶子节点上,所以每次查找都需要检索到叶子节点才能查询到数据。所以在需要查询数据的情况下每次的磁盘的IO跟树高有直接的关系,但是从另一方面来说,由于数据都被放到了叶子节点,所以放索引的磁盘块锁存放的索引数量是会跟这增加的,所以相对于B树来说,B+树的树高理论上情况下是比B树要矮的。也存在索引覆盖查询的情况,在索引中数据满足了当前查询语句所需要的全部数据,此时只需要找到索引即可立刻返回,不需要检索到最底层的叶子节点。
为什么MySQL最终选择B+树?
1、B+树内节点不存储数据,只存储索引,而B树内节点存储数据。所以B+树将业务数据和索引数据分离,B+树层级更少,查找更快,减少了磁盘I/O访问的次数。
2、B+Tree扫库和扫表能力更强。如果我们要根据索引去进行数据表的扫描,进行全节点扫描,对B TREE进行扫描,需要把整棵树遍历一遍,而B+树的叶子节点都维护了一个双向指针,B+TREE只需要遍历他的所有叶子节点即可(叶子节点之间有引用)。更加适合范围查找。
4、MySQL聚簇和非聚簇索引的区别
聚簇索引:将数据存储于索引放到了一块,并且是按照一定的顺序组织的,找到索引也就找到了数据,数据物理存放顺序和索引顺序是一致的,即只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。
非聚簇索引:叶子节点存储的不是数据,存储的数据行地址,也就是说根据索引查找到数据行的位置再取磁盘查找数据。类似于一本书的目录,索引是第几章第几节,那么存储的就是页码,然后数据存储在对应页码中。
聚簇索引的优势:
1、查询通过聚簇索引可以直接获取数据,相比非聚簇索引不需要第二次查询。
2、聚簇索引对于范围查询的效率很高。因为其数据是按照大小排列的。
3、聚簇索引适合用在排序的场合,非聚簇索引不适合。
聚簇索引的劣势:
1.维护索引很昂贵,插入速度严重依赖于插入顺序,按照主键的顺序插入是最快的方式,否则将会出现页分裂,严重影响性能。因此,对于InnoDB表,我们一般都会定义一个自增的ID列为主键
2.更新主键的代价很高,因为将会导致被更新的行移动。因此,对于InnoDB表,我们一般定义主键为不可更新。
3.二级索引访问需要两次索引查找,第一次找到主键值,第二次根据主键值找到行数据。
InnoDB中一定有主键,主键一定是聚簇索引,一般不手动设置,则会使用unique索引,没有unqiue索引,则会使用数据库内部的一个行的隐藏id来当作主键索引。在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。
MyISM使用的是非聚簇索引,非聚簇索引的两棵B+树看上去没什么不同,节点的结构完全一致只是存储的内容不同而已,主键索引B+树的节点存储了主键,辅助键索引B+树存储了辅助键。表数据存储在独立的地方,这两颗B+树的叶子节点都使用一个地址指向真正的表数据,对于表数据来说,这两个键没有任何差别。由于索引树是独立的,通过辅助键检索无需访问主键的索引树。
如果涉及到大数据量的排序、全表扫描、count之类,建议使用MyISM,因为索引所占空间小,这些操作需要在内存中完成。
5、 索引设计的原则?
遵循的原则:查询更快,占用空间更小:
1、适合索引的列一般是where中出现的列,或者是连接句子中指定的列。
2、基数较小的表(表的数据不多),索引效果较差,因为索引会额外的占用空间,因此没有必要建立索引。
3、不要过度索引,索引需要额外的磁盘空间,并降低写操作的性能,在修改表内容的时候,索引会进行更新沈直重构,所以只要保证需要的索引有利于查询即可。
4、定义有外键的列一定要建立索引。
5、更新频繁的字段不适合创建索引。
6、尽量使用扩展索引,不要新建索引,比如说表中已有了a的索引,现在最好加(a,b)的索引,那么就只需要修改原来的索引即可。
7、定义为text、image和bit的数据类型的列不要建立索引。
8、对于那些查询少涉及的列,重复值比较多的列不要建立索引。
6、简述mysql中索引类型及对数据库性能的影响?
普通索引:唯一任务是加快对数据的访问速度,允许被索引的数据包含重复的值
唯一索引:如何可以保证某个数据列将只包含彼此各不相同的值,那么可以将其设置为唯一索引,唯一索引可以保证数据记录的唯一性
主键:是一种特殊的唯一索引,在一张表中只能定义一个主键索引,但是可以定义多个唯一索引。
联合索引:索引可以覆盖多个数据列
全文索引:通过建立倒排索引,可以极大提升检索效率
索引可以极大的提高数据的查询效率,通过使用索引,可以在查询的过程中,使用优化隐藏起,提高系统的性能。
不正当使用索引会降低插入、删除、更新表的速度,因为在执行这些写操作时,还要操作索引文件;此外索引还会占据独立的物理空间。
7、为什么建议InnoDB表必须建主键,并且推荐使用整型的自增主键?
为什么建议InnoDB表必须建主键:
InnoDB采用B+树作为存储结构,那么必然需要一个列作为key,key 就是不重复的值且可以比较。主键的特定就是主键的值不可重复,也不可为空,正好符合B+树key的要求。如果不设置主键的,Mysql会在表中逐列对比寻找无重复项的列作为主键,如果没有查找到,那么Mysql会在表中添加默认列作为主键。如果不设置主键列,那么Mysql会消耗大量的资源去寻找索引列或者是创建新的索引列,如果设置了索引列那么将极大的降低Mysql的资源消耗。
为什么推荐整型的自增主键:
聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,将会不断地调整数据的物理地址、分页,造成大量的碎片。在B + 树的叶子节点中,通过双向指针维护了一根将索引按照升序排列的双向链表,采用自增主键,新的索引将会被添加在链表的尾部,避免了B + 树的分裂所带来的系统消耗。
MySQL中锁的相关面试题
1、MySQL中锁的类型有哪些?
1、按照锁的粒度把数据库锁分为行级锁、表级锁和页级锁:
表级锁是mysql锁中粒度最大的一种锁,表示当前的操作对整张表加锁,粒度大、加锁简单、容易造成冲突。
行锁是上锁的时候锁住表中某一行或多行记录,粒度较小,加锁麻烦,不易冲突,相比表锁支持的并发要高。
记录锁:事务在加锁后锁住的只是表的某一条记录
间隙锁:事务在加锁后锁住的是表记录的某一个区间
临建锁:临建锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间也会锁住。
页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。
2、按照属性可以分为共享锁和排他锁:
排他锁是指在给某行数据加上排他锁之后,其他事务不能再给该行数据加任何的排他锁和共享锁。
共享锁又称读锁,当一个事务为数据加上读锁后,其他事务只能对该数据加读锁,而不能加写锁。
2、什么是死锁?怎么解决?
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。
常见的解决死锁的方法:
1、如果不同程序会并发存取多个表,尽量约定以相同的顺序访问表,可以大大降低死锁机会。
2、在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁产生概率;
3、对于非常容易产生死锁的业务部分,可以尝试使用升级锁定颗粒度,通过表级锁定来减少死锁产生的概率;
3、数据库的乐观锁和悲观锁是什么?怎么实现的?
数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
乐观锁和悲观锁的概念:
悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。在修改数据的时候把事务锁起来,通过version的方式来进行锁定。实现方式:乐一般会使用版本号机制或CAS算法实现。
两种锁的使用场景
从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。
但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。
MySQL事务
1、MySQL事务的基本特性和隔离级别?
事务特性:
1.原子性: 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;
2.一致性: 执行事务前后,数据保持一致,多个事务对同一个数据读取的结果是相同的;以账户转账为例子进行分析:比如账户A账户有500块,B账户有100块,A向B转账100块,一致性保证事务只能A账户转了之后剩余400,B账户为200,只能是这种情况。
3.隔离性: 并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;
4.持久性: 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。
隔离级别:
READ-UNCOMMITTED(读取未提交): 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读取已提交): 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生。
REPEATABLE-READ(可重复读): 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
SERIALIZABLE(可串行化): 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。
注:Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别
脏读、幻读、不可重复读:
- 1.脏读(Drity Read):某个事务已更新一份数据,另一个事务在此时读取了同一份数据,由于某些原因,前一个RollBack了操作,则后一个事务所读取的数据就会是不正确的。
- 2.不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这可能是两次查询过程中间插入了一个事务更新的原有的数据。
- 3.幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例如有一个事务查询了几列(Row)数据,而另一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
2、Mysql主从同步基本原理?
从数据库(Slave)是主数据库的备份,当主数据库(Master)变化时从数据库要更新,这些数据库软件可以设计更新周期。这是提高信息安全的手段。主从数据库服务器不在一个地理位置上,当发生意外时数据库可以保存。
基本过程:
1.主节点binlog:主从复制的基础是主库记录数据库的所有变更记录到binlog。binlog是数据库服务器启动的那一刻起,保存所有修改数据库结构或内容的一个文件。
2、主节点线程log dump:当binlog中有数据变动时,log dump线程读取其中内容发送给从节点。
3、从节点I/O线程接收到binlog内容,并将其写入到relay log文件中去
4、从节点的SQL线程读取relay log文件内容对数据更新进行更改,最终保证主从数据库的一致。
注:mysql主从节点使用binlog+pos偏移量来定位主从同步的位置,从节点会保存其已接收到的偏移量,如果从节点发生宕机重启,则会自动从pos的位置发生同步。
三种主从同步的方式:异步主从同步、半主从同步、全主从同步。