Mysql面试题

目录

Mysql索引有哪些缺点?以及具体有哪些索引类型?

Mysql事务的实现原理?

说一下行锁、临键锁、间隙锁的理解?

MySQL表设计时间列用datetime还是timestamp? 

请说一下MySQL索引失效场景?

​编辑MySQL自增ID后会怎么样?

什么是最左匹配原则?

Mysql数据库CPU飙升要怎么处理?

Mysql索引有哪些缺点以及具体有哪些索引类型?

​编辑

Mysql的 binlog有几种格式?

怎么解决Mysql主从集群同步延迟问题?

Mysql中的RR隔离级别,到底有没有解决幻读问题? 

Mysql的性能调优方法

Mysql中MyISAM和InnoDB引擎有什么区别?

Mysql如何解决幻读问题? 

 Mysql为什么使用B+ Tree作为索引结构

Mysql的事务隔离级别


Mysql索引有哪些缺点?以及具体有哪些索引类型?

第一、索引的优缺点
优点:1.合理的增加索引,可以提高数据查询的效率,减少查询时间。
     2.有一些特殊的索引,可以保证数据的完整性。比如唯一索引。

缺点:1.对创建索引的表进行数据的增加、修改、删除时,会同步动态维护索引,这
     部分会造成性能影响。
     2.创建索引和维护索引需要消耗时间,并需要额外的占用物理空间

第二、索引的类型
    1.主键索引:(数据列不允许重复,不允许为null,一个表只能有一个主键)
    2.唯一索引:(数据列不允许重复,允许为null,一个表允许多个列创建索引)
    3.普通索引:(基本的索引类型,没有唯一性的限制,允许为null值)
    4.覆盖索引:查询列要被所建的索引覆盖,不必读取数据行
    5.组合索引:多列值组成一个索引,用于组合搜索,效率大于索引合并
     

Mysql事务的实现原理?

(Mysql里面的事务满足ACID特性。原理就是InnoDB是如何保证ACID这样一个特性。)
 首先,A表示Atomic原子性,需要保证多个DML操作的原子性【原子性:要么都成功,要么都失败】,
 那么失败就意味着,对原本执行成功的数据要进行回滚。所以在InnoDB里面设计一个UNDO_LOG表。
 在事务执行的过程中,把修改之前的数据快照保存到undo_log里面,一旦出现错误就直接从UNDO_LOG
 里面读取数据,进行反向操作就可以了。
 其次就是C,C表示一致性(数据的完整性约束没有被破坏),这个更多是依赖业务层面的一些保障。数据库
 本身提供了像主键的唯一约束、字段长度和类型的一些保障等等。
 接下来i,I表示事务的隔离性也就是说多个并行的事务对同一个数据进行操作的时候。如何去避免多个事务
 的干扰到数据混乱的一个问题。而InnoDB里面实现了SQL92的一个标准,提供了四种隔离级别的一个实现。
 1.RU(未提交读) 2.RC(已提交读) 3.RR(可重复读) 4.Serializable(串行化)
 InnoDB默认采用的隔离级别是RR,然后使用了MVCC机制,去解决了脏读和不可重复读的一个问题。然后使用
 了行锁/表锁的方式来解决了幻读的问题。
 最后一个是D(持久性),也就是说只要事务提交成功那么对于这个数据的结果的影响一定是永久的。不能因为数 
 据库宕机或者其他原因导致数据变更失效。

 理论上,事务提交之后,直接把数据放到磁盘中就0K了。但是随机磁盘IO效率确实很低,所以InooDB
 里面设计了Buffer Pool缓存区进行优化,也就是说数据发生变更的时候,先更新内存缓冲区,然后
 在合适的时间再持久化到磁盘里面。
 那么在这个机制里面,有可能出现在持久化这样一个过程中数据库宕机就会导致数据丢失。(无法满足
 持久化)。所以在InnoDB中引入了Redo_LOG这样一个文件。这个文件存储了数据库变更之后的一个值,
 当我们通过事务进行数据更改的时候,除了修改内存缓存区的数据以外还会把本次修改的一个值追加到
 Redo_LOG里面。当事务提交的时候,直接把Redo_LOG里面的日志刷新到磁盘里面进行持久化。一旦
 数据库发生宕机,在mysql重启之后直接用Redo_LOG里面保存的重写日志读取出来以后再去执行一次。
 从而去保证数据的持久性。

 总的来看,事务的持久性原理核心本质原理就是如何去保证事务的ACID特性。而在UNDO_LOG里面用到了
 MVCC、行锁、表锁、UNDO_LOG以及Redo_LOG等等这些机制去保证事务的ACID特性。

 (设计思想:乐观锁、利用内存的缓冲区的方式来以空间换时间的思想去优化磁盘io的性能等等。
  比如在分布式事务框架Seata的AT模式的数据回滚就借鉴了InnDB里面的UNDO_LOG的设计思想)

说一下行锁、临键锁、间隙锁的理解?

都是Mysql里面InnoDB引擎下去解决事务隔离性的一系列排他锁。
行锁:也称为记录锁,当我们针对组件或者唯一索引加锁的时候Mysql默认会对查询这行数据增加行锁,
避免其他事务对这一行数据进行修改。
(--其中id为主键索引 SELECT * FROM test WHERE  id =1 FOR UPDATE;)

间隙锁:就是锁定一个索引区间。在普通索引或者唯一索引的列上,由于索引基于B+树的一个结构存储。
所以默认会存在一个索引的一个区间。就是某个事务对索引列加锁的时候,默认锁定对应索引的左右开区
间的一个范围。在基于索引类范围的查询中无论是否是唯一索引都会自动触发一个间隙锁。比如基于
between范围查找的过程中就会产生一个左右开区间的一个间隙锁。
(比如:--锁定:(5,7)select * from test where id between 5 and 7 fro update)

临键锁:它相当于行锁+间隙锁的一个组合,也就是说它的锁定范围既包含**索引记录**也包含了**索引
区间**,它会锁定一个左开右闭的一个数据范围。
-- 临键锁,锁定区间(10,11] select * from test where age=ll for update;
假设我们使用非唯一索引进行查询默认会加一个临键锁,锁定一个左开右闭区间一个范围。

所以总的来说行锁、临键锁和间隙锁它只是表示锁的数据的一个范围,终目的是为了解决幻读的这样一个问题。
而临键锁相当于行锁+间隙锁的一个组合。因此我们使用非唯一索引进行精准匹配的时候会默认加一个临建锁。
因为需要锁定匹配的一行记录还需要锁定这一行数据对应的左开右闭区间。因此在实际应用过程中尽可能
的就是使用**唯一索引**或者**主键索引**进行数据查询。避免大面积锁定造成性能的影响。


考核:关于事务隔离级别以及解决事务隔离级别一些底层实现
     如何在保证数据安全性的情况下去平衡性能

 Mysql中的数据预加载机制引发的思考?

 问题解析:
    Mysql在数据IO层面面临挑战,以及它的解决思路。Mysql数据存储到磁盘上,而读写磁盘的
 速度相对内存来说是很慢的。所以为了优化磁盘IO性能,在Mysql中引入了一个缓冲池的概念。
(Buffer_pool机制)它会把一部分经常访问的数据缓存到内存里面,从而去提高数据的访问速度。
有了缓冲池以后当读取数据的时候,如果数据存在于Buffer Pool中。
    客户端会直接读取Buffer Pool中的数据,否则再会去磁盘读取。
    客户端修改数据的时候,首先也是修改Buffer Pool中数据所在的页,然后再把它的页设置为
    脏页。最后由后台线程把脏页写入磁盘中。缓冲池的存在很大程度上减少了磁盘I/O带来的性能
    开销。要操作的数据行所在的数据页如果存在缓存中的话,就不需要从磁盘中读取了。这样执行
    以后就可以快速拿到结果。所以只要不存在或者减少磁盘I/O执行速度自然就会变快。
而预加载机制,就是更进一步减少磁盘IO的一个方式,InnoDB会把存储的数据划分为若干个页。以页
作为磁盘和内存交互的一个基本单位。一个页的默认大小是16kb,也就是一次读取会读取16kb的数据
缓存到Buffer Pool中。但是在程序中是有个叫空间局部性特征,也就是说当前读取磁盘上这一个数
据相邻的数据在未来很大概率也会被使用到。所以Mysql在加载数据页的时候会提前把它相邻的数据页
一并加载进来。目的就是为了减少磁盘IO,这就是所谓的预加载机制。在Mysql中提供了线性预读和随
机预读两种实现方式。
    总的来说,基于空间局部原理实现预加载机制以及空间换时间思想下实现的Buffer Pool缓存池
的机制,都是在解决磁盘IO性能问题的设计方案。

Mysql中那些令人震撼架构设计思想

为了实现CRUD数据存储(索引、事务、存储)
问题分析:Mysql数据库的数据是存储在磁盘上的,当执行一条查询语句的时候,理论上Mysql需要
从磁盘上进行多次随机IO获取数据内容,进行返回。很明显由于磁盘IO性能相对比较低会导致一次查
询可能需要几十秒的响应,这显然不符合企业级应用的需求。因此Mysql为了解决这些性能问题做了几
方面的优化:
    1.如图1引入了Buffer_pool缓冲池的设计,它是在内存中开辟了一块区域用来缓冲磁盘中的数
    据;在Mysql启动的时候,InnoDB会为Buffer Pool申请一片连续的内存空间,然后按照默认的
    16kb大小划分为一个一个的页(Buffer_pool中的页叫缓存页)。此时缓存页都是空闲的之后随着
    程序的运行才会有磁盘上的数据页被缓存到Buffer_pool中。(这是一种典型的空间换时间的设计
    思想:比如Mybits的多级缓存设计) 
    2.引入索引机制:依然是解决磁盘IO性能较慢的问题。具体来说,如果我们想查找指定的数据行
    那么我们需要多次磁盘IO进行寻址。如果数据量很大的情况下IO次数会非常多,而且性能会比较
    差。而通过索引的方式来组织数据存储,可以减少磁盘IO的次数。
    3.引入查询优化器:使得用户提交了查询sql的执行计划,能够达到一个相对比较好的水平。
    4.Mysql在数据持久化的时候,采用了追加的方式。记录到REDO_LOG的日志文件中,追加是采用
    了一个磁盘顺序写。磁盘顺序写的性能是很高的,几乎和内存的随机读写的性能差不多。因此数据
    写入磁盘的性能同样得到了很大的提升。
    另外在解决事务并行冲突的场景中,引入了MVCC乐观锁的设计,降低了加锁带来的性能开销的影响。

MySQL表设计时间列用datetime还是timestamp? 

问题解析:
MYSQL中时间列的选择问题涉及到许多方面的考虑,包括存储空间、时区支持、时间范围等等。
选择合适的时间类型不仅能够让你的数据库更加高效,还有助于避免一些常见的时间相关错误。
面试官提出这个问题的目的可能是了解你是否能够根据项目中的实际需求来做出合理的数据库
设计决策。

问题回答:
从三个方面来回答,
1.datetime和timestamp的区别,首先存入空间层面,timestamp占用四个字节,而
datetime占用八个字节。所以如果对存储空间有严格要求,Timestamp是一个更好的选择。
其次是时区支持timeStamp存储的是一个utc时间,会根据系统时序进行一个自动转化,
而datetime,不会做持续转化,存储的是字面值的时间。如果这业务程序需要在不同的时序
之间进行工作,那么timestamp可能是一个更合适的选择。接下来就是时间范围,datetime
的时间范围从1000年到9999年,timestamp它的时间范围是1970年到2038年。所以你需要
根据表述的时间范围来选择
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值