mysql常见面试题

MYSQL

基础知识:

sql注入:

当sql语句绑定有参数输入时,可通过外部更改URL的方式,将sql语句进行更改(union),这样就可以在未获取正确数据的情况下访问系统,对系统的安全性造成破坏

mybatis如何在插入数据后获取主键值:xml中useGeneratekeys属性设置为true

数据库中间件技术:

mycat,当mysql设为集群架构时,项目连接mycat,mycat连接mysql集群,这样项目就感觉直接连了一个mysql,而不是mysql集群。

mysql的执行流程

mysql常见面试题

客户端(jdbc,navicat)操作mysql->连接器->分析器->优化器->执行器->存储引擎(存储引擎就是一种持久化数据的工具、数据的存储格式)

sql执行的步骤:

from join on where groupby having select disInct orderby limit

MySql中的索引

常见的也就两种:hash和B+Tree

  • hash:hash索引的话,它的存储过程其实和hashmap很像,根据索引列对应的值计算出hash后存储起来,不过hash会有hash冲突,比较占用内存且不支持范围查找

  • B+Tree:使用B+Tree比较多,每个结点存放16KB数据页的数据,非叶子结点的数据页中包括了索引值和指向下一个结点的指针,所有数据都是在叶子节点中按从小到大的顺序存放的。

对于myIsam存储引擎来说,叶子结点存放的其实是索引对应的数据所在磁盘文件的地址。

对于InnoDB存储引擎来说,叶子结点存放的就是索引对应的数据。

mysql的索引优化:

索引就是一个用来排序+查找的数据结构减少io次数从而提高效率,它底层是用B+树实现,一个表中最多可建立16个索引

  • 创建索引的方式:createIndex xxx on tableName(字段1,字段2)

  • 删除索引的方式:dropIndex xxx on tableName

  • 查看索引的方式:show Index from tableName

mysql中的存储引擎:InnoDB MyIsam

InnoDB和MyIsam的区别:

  • 一:InnoDB支持行锁(innodb只有在使用索引时采用行锁,其他情况使用表锁),MyIsam是表锁

  • 二:InnoDB支持事务,MyIsam不支持事务

  • 三:InnoDB支持外键,MyIsam不支持外键

  • 四:InnoDB支持聚集索引,MyIsam不支持

  • 五:InnoDB的数据文件:.frm:表结构,.ibd:索引+数据,MyIsam的数据文件:.frm:表结构,.MYI:索引,.MYD:数据

索引:

索引的种类

  • 唯一索引:所建立的索引所属列的值必须是唯一的,且可以为null

  • 复合索引:一个索引中包含多个列

  • 单值索引:一个索引只包括单个列,一个表中可以有多个单值索引

  • 聚集索引:也就是主键索引,每个表中只要有主键那么该主键就自带聚集索引,若没有主键那么mysql会选择一个值不重复的列作为聚集索引,若不存在则它会建立一个隐藏的自增字段作为聚集索引

聚集索引和非聚集索引的区别?

聚集索引要求字段的值唯一,聚集索引在叶子节点存放的是表中所有的数据,非聚集索引在叶子节点存放的是主键id和索引列对应的数据 (非聚集索引不采用覆盖索引时要进行回表操作)

覆盖索引:

指要查询的字段都属于一个索引中的字段,就称为覆盖索引,无需做回表操作,(回表:当要查询的字段大于索引的字段时,需要回表到聚簇索引中再查询二级索引中不包括的字段对应的值)

哪些列适合作为索引?

  • 经常被查询的列

  • 数据量大

  • 值大多都不重复的

  • 外连接查询时On条件后面的字段,经常用于排序的列

哪些情况不适合建立索引?

  • 列中有很多重复的值

  • 经常用于增删改的列

  • 表记录太少

索引失效的原因:

  • 一:未遵循最佳左前缀原则,where条件查询时,应该按照索引的顺序进行查询,不能缺少索引中的字段(缺少的字段后面的索引字段将失效),全职匹配我最爱

  • 二:范围查找后失效(> < !=),范围查找会导致索引失效,范围超找后面的条件会用不到索引

  • 三:不在索引列上做操作,如在where条件后的字段做(函数,类型转换)会导致索引失效

  • 四:like查询时%最好用在右边,否则会导致索引失效(除非采用覆盖索引(要查询的列和索引的列正好匹配))

  • 五:is null 和is not null和or 会导致索引失效

  • 六:尽量不要使用select *多使用覆盖索引,否则会造成回表操作(当用到我们自己创建的索引后,由于索引中存放的只有对应列的数据,select * 查询的是所有数据,因为还需要到主键索引中去获取对应的所有数据)

  • 七:在使用左连接时,要为右边的表建立索引,在使用右连接时,要为左边的表建立索引

sql优化:

  • ①:当大批量插入数据时,可以采用foreach标签批量插入而不是在JAVA中使用for循环插入

  • ②:优化limit分页,当查询的数据很靠后eg:limit:10000,10,可以采用:where id>10000 limit 10

  • ③:删除冗余索引,eg:索引1(age) 索引2(age,name) 就可以删除掉索引1,因为索引2包括索引:(age)和(age,name)

  • ④:where子句中考虑使用默认值代替null:where age is not null可以替换成where age >0

索引优化:

Explain+sql语句对sql进行分析 所显示的字段有

  • id(决定查询出来的多个表要执行的顺序):id相同时:执行顺序从上至下,id不同时:id越大的越先执行

  • select_type(显示查询的类型):simple:简单的sql查询 primary:最外层的查询 subquery:子查询

table(显示该行数据属于哪张表)

  • type(显示该行数据所用的类型):从好到坏 systetm>const>eq_Ref>ref>range>index>all 至少要达到range级别

  • possible_keys:显示可能用到的索引 key:实际用到的索引

  • key_len:索引用到的字节数

  • ref:哪些列用到了索引

  • rows:根据表的信息及索引的信息,估计出需要查找多少行可以找到对应的数据

慢查询日志

在开启慢查询日志后可以借助mysqlDrumpslow工具对慢查询日志进行分析。SQL执行时间超过long_query_time将会被记录到慢查询日志当中,可以通过explain关键字对其进行分析

show profile(Explain的升级版)记录最近执行的15条sql

mysql的事务:ACID

  • 原子性:事务内的操作要么都成功,要么都失败(mysql用undo log实现)

  • 一致性:事务提交前和提交后,数据库的完整性约束没有被破坏

  • 隔离性:多个事务间是相互隔离的互不影响

  • 永久性:事务提交后,所修改的数据是永久生效的

MVVC:

多版本并发控制,行锁的变种,在多线程操作数据库时保证事务隔离的机制,可以降低锁竞争的压力,保证较高的并发量。

在InnoDB存储引擎中,MVVC会在每行数据后保存两个隐藏的列来实现,分别是数据创建时间和删除时间,当然这个时间并不是真正的创建、删除时间,而是系统版本号,没开启一个新的事务版本号就会递增,事务开始时的版本号作为事务的版本号,用来和查询到的数据的版本号进行比较。

redoLog:

是InnoDB存储引擎的,用于保证事务的安全,在mysql重启后,会根据redolog进行重做从而达到事务的永久性

undoLog:

记录了事务提交前的数据的一个版本,可用于回滚,同时也保证了多版本并发控制下的读

事务并发带来的问题:

  • 更新丢失:A和B同时更新,后面更新的数据会覆盖掉之前更新的数据

  • 脏读:A读到了B未提交的数据

  • 不可重复度:A读到了B已提交的修改数据

  • 幻读:A读到了B已提交的新增数据

事务的隔离级别(通过mysql锁的机制实现)

  • 读未提交:读取到了还没有提交事务的数据

  • 读已提交:读取到了已经提交的新增数据(可避免脏读)

  • 可重复度:可以读到已提交的修改数据(可避免脏读,不可重复度)

  • 可序列化(都可以避免)

事务的传播机制:

  • Required:B方法在A方法中被调用,若A开启事务,则B就和A用同一事务

  • RequiresNew:B方法在A方法中被调用,若A开启事务,则B开启一个新事务,B和A的事务相互独立

  • Nested:B方法在A方法中被调用,若A开启事务,则B开启一个新事务,当A事务回滚则B事务也回滚,若B事务回滚A没事

主从复制:

将mysql进行主从复制,主库(master)负责写,从库(slave)负责读,实现读写分离和故障切换的高可用 原理:主库将改变记录到二进制日志中(binary log) 从库读取主库的binary log 日志并拷贝到它的中继日志当中 从库重做中继日志中的事件,将改变应用到自己的数据库中 问题:延时,从库无法第一时间读取到主库新增的数据 解决方法:读取新增数据时,让他强制到主库中进行读取

三大范式

  • 第一范式:数据库中的各个字段,都是不可分割的。(地区:中国山西,这个就可以分割为中国和山西)

  • 第二范式:在满足第一范式的基础上,保证各个字段都是依赖于主键的。(若该字段离开主键照样可以知道值,也不算第二范式)

  • 第三范式:在满足第二范式的基础上,各个字段不能有依赖关系(单价:10 数量:5 总价:50,这个总价就可以通过单价*数量算出来,就不符合第三范式了)

分表技术

分为水平分表和垂直分表(用数据库中间件技术mycat实现) 水平分表:当表中数据太多时,可按行分表(原来200行的表分为2个100行数据的表) 垂直分表:当表中字段太多时,可将一些不常用的字段分离到新的表上,通过外键关联(5个字段的表,分为一个4个字段一个1个字段的表)

mysql5.7推出的索引下推

可以减少回表次数,它会先在索引表(二级索引)中对索引表中的字段进行判断,直接过滤掉不满足条件的记录,减少回表次数。

eg:select age,name,email from user where age=18 and name=’guo’

此时拥有索引:(age,name)

在5.7之前的查询:根据最左匹配原则直接根据age=18做数据过滤,然后获取到2条记录,再回表获取到email的数据,然后再到server层根据name=’guo’做数据的过滤最终获取到结果。

在5.7之后的查询:现在在执行引擎中直接会对age=18,name=’guo’来作为条件进行过滤查询,得到一个记录后回表获取email的数据,最终获取到结果。

简单来说索引下推就是将server层的数据过滤下推到了存储引擎层,来减少回表

常见问题

*唯一索引普通索引选择难题

唯一索引无法使用changebuffer,普通索引可以使用 执行更新操作,判断数据页是否在内存,在内存直接更新,不在内存则将其缓存到changebuffer执行merge操作

一个很长的字段,想做索引我们怎么去优化它

因为字段很长,所以要建立B+树索引的话,索引所占的磁盘空间就越大,搜索效率就不高 可以使用hash索引,把字段hash为另一个字段存起来,每次校验hash就可以了

select *和 select 全部字段的区别

select *要解析数据字典,select 全部字段不需要 select 全部字段更具有可读性 select全部字段 可以按指定字段顺序输出,select *按照建表顺序输出

having和where的区别

having是在分组group by时使用 having在where后执行 having无法用到索引,where可以 having可以用到聚集函数,where不可以

PreparedStatment和Statment区别

statment会频繁编译sql PreparedStatment可以对sql预编译,提高效率 当sql中有条件时,PreparedStatment可以使用占位符,statment则需要进行拼接,因此statment有SQL注入问题

数据库连接池:

因为每次获取和释放连接都很耗时,因此有了数据库连接池,在项目启动时就建立一定数量的池连接,获取连接时从池中获取,释放连接时,不是将连接直接释放掉,而是将连接再归还到连接池当中。(底层通过list集合来对连接进行存放)当有连接请求到连接池,如果有连接处于空闲状态则直接返回一个空闲连接并标记为忙。如果当前没有空闲连接,就会新建一定数量的连接,新建连接的数量由配置参数决定。


原文始发于微信公众号(GuoCoding):mysql常见面试题

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/43009.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!