Mysql大厂高频面试题
时间 2021-08-12
标签
mysql
web
面试
redis
算法
sql
数据库
缓存
安全
服务器
前言
Mysql面试题
什么是SQL?
什么是MySQL?
数据库三大范式是什么?
-
`第一范式`:每一个列都不能够再拆分。
-
`第二范式`:在第一范式的基础上,非主键列彻底依赖于主键,而不能是依赖于主键的一部分。
-
`第三范式`:在第二范式的基础上,非主键列只依赖于主键,不依赖于其余非主键。
-
在设计数据库结构的时候,要尽可能遵照三范式,若是不遵照,必须有足够的理由。好比性能。事实上咱们常常会为了性能而妥协数据库的设计。
mysql有关权限的表都有哪几个?
-
MySQL服务器经过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化。这些权限表分别user,db,table_priv,columns_priv和host。下面分别介绍一下这些表的结构和内容:
-
`user权限表`:记录容许链接到服务器的用户账号信息,里面的权限是全局级的。
-
`db权限表`:记录各个账号在各个数据库上的操做权限。
-
`table_priv权限表`:记录数据表级的操做权限。
-
`columns_priv权限表`:记录数据列级的操做权限。
-
`host权限表`:配合db权限表对给定主机上数据库级操做权限做更细致的控制。这个权限表不受GRANT和REVOKE语句的影响。
MySQL的binlog有有几种录入格式?分别有什么区别?
mysql有哪些数据类型?
MyISAM索引与InnoDB索引的区别?
-
InnoDB索引是聚簇索引,MyISAM索引是非聚簇索引。
-
InnoDB的主键索引的叶子节点存储着行数据,所以主键索引很是高效。
-
MyISAM索引的叶子节点存储的是行数据地址,须要再寻址一次才能获得数据。
-
InnoDB非主键索引的叶子节点存储的是主键和其余带索引的列数据,所以查询时作到覆盖索引会很是高效。
InnoDB引擎的4大特性
-
插入缓冲(insert buffer)
-
二次写(double write)
-
自适应哈希索引(ahi)
-
预读(read ahead)
什么是索引?
-
索引是一种特殊的文件(InnoDB数据表上的索引是表空间的一个组成部分),它们包含着对数据表里全部记录的引用指针。
-
索引是一种数据结构。数据库索引,是数据库管理系统中一个排序的数据结构,以协助快速查询、更新数据库表中数据。索引的实现一般使用B树及其变种B+树。
-
更通俗的说,索引就至关于目录。为了方便查找书中的内容,经过对内容创建索引造成目录。索引是一个文件,它是要占据物理空间的。
索引有哪些优缺点?
索引有哪几种类型?
索引的数据结构(b树,hash)
1. B树索引mysql
2. B+tree性质web
-
n棵子tree的节点包含n个关键字,不用来保存数据而是保存数据的索引。
-
全部的叶子结点中包含了所有关键字的信息,及指向含这些关键字记录的指针,且叶子结点自己依关键字的大小自小而大顺序连接。
-
全部的非终端结点能够当作是索引部分,结点中仅含其子树中的最大(或最小)关键字。
-
B+ 树中,数据对象的插入和删除仅在叶节点上进行。
-
B+树有2个头指针,一个是树的根节点,一个是最小关键码的叶节点。
3. 哈希索引面试
索引的基本原理
索引算法有哪些?
1. BTree算法redis
-
BTree是最经常使用的mysql数据库索引算法,也是mysql默认的算法。由于它不只能够被用在=,>,>=,<,<=和between这些比较操做符上,并且还能够用于like操做符,只要它的查询条件是一个不以通配符开头的常量。
2. Hash算法算法
索引设计的原则?
-
适合索引的列是出如今where子句中的列,或者链接子句中指定的列。
-
基数较小的类,索引效果较差,没有必要在此列创建索引
-
使用短索引,若是对长字符串列进行索引,应该指定一个前缀长度,这样可以节省大量索引空间
-
不要过分索引。索引须要额外的磁盘空间,并下降写操做的性能。在修改表内容的时候,索引会进行更新甚至重构,索引列越多,这个时间就会越长。因此只保持须要的索引有利于查询便可。
建立索引的原则
-
索引虽好,但也不是无限制的使用,最好符合一下几个原则
-
最左前缀匹配原则,组合索引很是重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是创建(a,b,c,d)顺序的索引,d是用不到索引的,若是创建(a,b,d,c)的索引则均可以用到,a,b,d的顺序能够任意调整。
-
较频繁做为查询条件的字段才去建立索引
-
更新频繁字段不适合建立索引
-
如果不能有效区分数据的列不适合作索引列(如性别,男女未知,最多也就三种,区分度实在过低)
-
尽可能的扩展索引,不要新建索引。好比表中已经有a的索引,如今要加(a,b)的索引,那么只须要修改原来的索引便可。
-
定义有外键的数据列必定要创建索引。
-
对于那些查询中不多涉及的列,重复值比较多的列不要创建索引。
-
对于定义为text、image和bit的数据类型的列不要创建索引。
建立索引时须要注意什么?
-
非空字段:应该指定列为NOT NULL,除非你想存储NULL。在mysql中,含有空值的列很难进行查询优化,由于它们使得索引、索引的统计信息以及比较运算更加复杂。你应该用0、一个特殊的值或者一个空串代替空值;
-
取值离散大的字段:(变量各个取值之间的差别程度)的列放到联合索引的前面,能够经过count()函数查看字段的差别值,返回值越大说明字段的惟一值越多字段的离散程度高;
-
索引字段越小越好:数据库的数据存储以页为单位一页存储的数据越多一次IO操做获取的数据越大效率越高。
使用索引查询必定能提升查询的性能吗?
-
一般,经过索引查询数据比全表扫描要快。可是咱们也必须注意到它的代价。
-
索引须要空间来存储,也须要按期维护, 每当有记录在表中增减或索引列被修改时,索引自己也会被修改。 这意味着每条记录的INSERT,DELETE,UPDATE将为此多付出4,5 次的磁盘I/O。 由于索引须要额外的存储空间和处理,那些没必要要的索引反而会使查询反应时间变慢。使用索引查询不必定能提升查询性能,索引范围查询(INDEX RANGE SCAN)适用于两种状况:
-
基于一个范围的检索,通常查询返回结果集小于表中记录数的30%
-
基于非惟一性索引的检索
百万级别或以上的数据如何删除?
-
关于索引:因为索引须要额外的维护成本,由于索引文件是单独存在的文件,因此当咱们对数据的增长,修改,删除,都会产生额外的对索引文件的操做,这些操做须要消耗额外的IO,会下降增/改/删的执行效率。因此,在咱们删除数据库百万级别数据的时候,查询MySQL官方手册得知删除数据的速度和建立的索引数量是成正比的。
-
因此咱们想要删除百万数据的时候能够先删除索引(此时大概耗时三分多钟)
-
而后删除其中无用数据(此过程须要不到两分钟)
-
删除完成后从新建立索引(此时数据较少了)建立索引也很是快,约十分钟左右。
-
与以前的直接删除绝对是要快速不少,更别说万一删除中断,一切删除会回滚。那更是坑了。
什么是最左前缀原则?什么是最左匹配原则?
-
顾名思义,就是最左优先,在建立多列索引时,要根据业务需求,where子句中使用最频繁的一列放在最左边。
-
最左前缀匹配原则,很是重要的原则,mysql会一直向右匹配直到遇到范围查询(>、<、between、like)就中止匹配,好比a = 1 and b = 2 and c > 3 and d = 4 若是创建(a,b,c,d)顺序的索引,d是用不到索引的,若是创建(a,b,d,c)的索引则均可以用到,a,b,d的顺序能够任意调整。
-
=和in能够乱序,好比a = 1 and b = 2 and c = 3 创建(a,b,c)索引能够任意顺序,mysql的查询优化器会帮你优化成索引能够识别的形式
B树和B+树的区别
使用B树的好处
使用B+树的好处
什么是聚簇索引?什么时候使用聚簇索引与非聚簇索引?
非聚簇索引必定会回表查询吗?
联合索引是什么?为何须要注意联合索引中的顺序?
-
MySQL可使用多个字段同时创建一个索引,叫作联合索引。在联合索引中,若是想要命中索引,须要按照创建索引时的字段顺序挨个使用,不然没法命中索引。
-
MySQL使用索引时须要索引有序,假设如今创建了"name,age,school"的联合索引,那么索引的排序为: 先按照name排序,若是name相同,则按照age排序,若是age的值也相等,则按照school进行排序。
-
当进行查询时,此时索引仅仅按照name严格有序,所以必须首先使用name字段进行等值查询,以后对于匹配到的列而言,其按照age字段严格有序,此时可使用age字段用作索引查找,以此类推。所以在创建联合索引的时候应该注意索引列的顺序,通常状况下,将查询需求频繁或者字段选择性高的列放在前面。此外能够根据特例的查询或者表结构进行单独的调整。
什么是数据库事务?
事物的四大特性(ACID)介绍一下?
-
`原子性`: 事务是最小的执行单位,不容许分割。事务的原子性确保动做要么所有完成,要么彻底不起做用;
-
`一致性`: 执行事务先后,数据保持一致,多个事务对同一个数据读取的结果是相同的;
-
`隔离性`: 并发访问数据库时,一个用户的事务不被其余事务所干扰,各并发事务之间数据库是独立的;
-
`持久性`: 一个事务被提交以后。它对数据库中数据的改变是持久的,即便数据库发生故障也不该该对其有任何影响。
什么是脏读?幻读?不可重复读?
-
`脏读`(Drity Read):某个事务已更新一份数据,另外一个事务在此时读取了同一份数据,因为某些缘由,前一个RollBack了操做,则后一个事务所读取的数据就会是不正确的。
-
`不可重复读`(Non-repeatable read):在一个事务的两次查询之中数据不一致,这多是两次查询过程当中间插入了一个事务更新的原有的数据。
-
`幻读`(Phantom Read):在一个事务的两次查询中数据笔数不一致,例若有一个事务查询了几列(Row)数据,而另外一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
什么是事务的隔离级别?MySQL的默认隔离级别是什么?
隔离级别与锁的关系
-
在Read Uncommitted级别下,读取数据不须要加共享锁,这样就不会跟被修改的数据上的排他锁冲突
-
在Read Committed级别下,读操做须要加共享锁,可是在语句执行完之后释放共享锁;
-
在Repeatable Read级别下,读操做须要加共享锁,可是在事务提交以前并不释放共享锁,也就是必须等待事务执行完毕之后才释放共享锁。
-
SERIALIZABLE 是限制性最强的隔离级别,由于该级别锁定整个范围的键,并一直持有锁,直到事务完成。
按照锁的粒度分数据库锁有哪些?
-
`行级锁`:行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操做的行进行加锁。行级锁能大大减小数据库操做的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁 和 排他锁。特色:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的几率最低,并发度也最高。
-
`表级锁`: 表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操做的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为表共享读锁(共享锁)与表独占写锁(排他锁)。特色:开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的几率最高,并发度最低。
-
`页级锁`:页级锁是MySQL中锁定粒度介于行级锁和表级锁中间的一种锁。表级锁速度快,但冲突多,行级冲突少,但速度慢。因此取了折衷的页级,一次锁定相邻的一组记录。
从锁的类别上分MySQL都有哪些锁呢?
InnoDB存储引擎的锁的算法有哪三种?
什么是死锁?怎么解决?
数据库的乐观锁和悲观锁是什么?怎么实现的?
-
数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段。
-
`悲观锁`:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操做。在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制
-
`乐观锁`:假设不会发生并发冲突,只在提交操做时检查是否违反数据完整性。在修改数据的时候把事务锁起来,经过version的方式来进行锁定。实现方式:乐通常会使用版本号机制或CAS算法实现。
大表数据查询,怎么优化?
-
优化shema、sql语句+索引;
-
第二加缓存,memcached, redis;
-
主从复制,读写分离;
-
垂直拆分,根据你模块的耦合度,将一个大的系统分为多个小的系统,也就是分布式系统
-
水平切分,针对数据量大的表,这一步最麻烦,最能考验技术水平,要选择一个合理的sharding key, 为了有好的查询效率,表结构也要改动,作必定的冗余,应用也要改,sql中尽可能带sharding key,将数据定位到限定的表上去查,而不是扫描所有的表
超大分页怎么处理?
-
超大的分页通常从两个方向上来解决:
-
数据库层面,这也是咱们主要集中关注的(虽然收效没那么大),相似于select * from table where age > 20 limit 1000000,10这种查询其实也是有能够优化的余地的. 这条语句须要load1000000数据而后基本上所有丢弃,只取10条固然比较慢. 当时咱们能够修改成select * from table where id in (select id from table where age > 20 limit 1000000,10).这样虽然也load了一百万的数据,可是因为索引覆盖,要查询的全部字段都在索引中,因此速度会很快. 同时若是ID连续的好,咱们还能够select * from table where id > 1000000 limit 10,效率也是不错的,优化的可能性有许多种,可是核心思想都同样,就是减小load的数据
-
从需求的角度减小这种请求…主要是不作相似的需求(直接跳转到几百万页以后的具体某一页.只容许逐页查看或者按照给定的路线走,这样可预测,可缓存)以及防止ID泄漏且连续被人恶意***
为何要尽可能设定一个主键?
主键使用自增ID仍是UUID?
-
推荐使用自增ID,不要使用UUID。
-
由于在InnoDB存储引擎中,主键索引是做为聚簇索引存在的,也就是说,主键索引的B+树叶子节点上存储了主键索引以及所有的数据(按照顺序),若是主键索引是自增ID,那么只须要不断向后排列便可,若是是UUID,因为到来的ID与原来的大小不肯定,会形成很是多的数据插入,数据移动,而后致使产生不少的内存碎片,进而形成插入性能的降低。
-
总之,在数据量大一些的状况下,用自增主键性能会好一些。
-
关于主键是聚簇索引,若是没有主键,InnoDB会选择一个惟一键来做为聚簇索引,若是没有惟一键,会生成一个隐式的主键。
字段为何要求定义为not null?
若是要存储用户的密码散列,应该使用什么字段进行存储?
数据库结构优化?
-
一个好的数据库设计方案对于数据库的性能每每会起到事半功倍的效果。
-
须要考虑数据冗余、查询和更新的速度、字段的数据类型是否合理等多方面的内容。
-
**将字段不少的表分解成多个表**:对于字段较多的表,若是有些字段的使用频率很低,能够将这些字段分离出来造成新表。由于当一个表的数据量很大时,会因为使用频率低的字段的存在而变慢。
-
**增长中间表**:对于须要常常联合查询的表,能够创建中间表以提升查询效率。经过创建中间表,将须要经过联合查询的数据插入到中间表中,而后将原来的联合查询改成对中间表的查询。
-
**增长冗余字段**:设计数据表时应尽可能遵循范式理论的规约,尽量的减小冗余字段,让数据库设计看起来精致、优雅。可是,合理的加入冗余字段能够提升查询速度。表的规范化程度越高,表和表之间的关系越多,须要链接查询的状况也就越多,性能也就越差。
MySQL数据库cpu飙升到500%的话他怎么处理?
-
当 cpu 飙升到 500%时,先用操做系统命令 top 命令观察是否是 mysqld 占用致使的,若是不是,找出占用高的进程,并进行相关处理。
-
若是是 mysqld 形成的, show processlist,看看里面跑的 session 状况,是否是有消耗资源的 sql 在运行。找出消耗高的 sql,看看执行计划是否准确, index 是否缺失,或者实在是数据量太大形成。
-
通常来讲,确定要 kill 掉这些线程(同时观察 cpu 使用率是否降低),等进行相应的调整(好比说加索引、改 sql、改内存参数)以后,再从新跑这些 SQL。
-
也有多是每一个 sql 消耗资源并很少,可是忽然之间,有大量的 session 连进来致使 cpu 飙升,这种状况就须要跟应用一块儿来分析为什么链接数会激增,再作出相应的调整,好比说限制链接数等。
主从复制的做用?
-
主数据库出现问题,能够切换到从数据库。
-
能够进行数据库层面的读写分离。
-
能够在从数据库上进行平常备份。
MySQL主从复制解决的问题?
MySQL主从复制工做原理?
-
在主库上把数据更高记录到二进制日志
-
从库将主库的日志复制到本身的中继日志
-
从库读取中继日志的事件,将其重放到从库数据中。