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;
假设我们使用非唯一索引进行查询默认会加一个临键锁,锁定一个左开右闭区间一个范围。

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


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

你可能感兴趣的:(Java,java)