java面试10-MySQL

115 阅读8分钟

1、MySQL中myisam与innodb的区别

MyISAM:

  • 不支持事务,但是每次查询都是原子的;
  • 支持表级锁,即每次操作对整个表加锁;
  • 存储表的总行数;
  • 一个MYISAM表有三个文件:索引文件、表结构文件、数据文件;
  • 采用 ,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。

InnoDb:

  • 支持ACID的事务,支持事务的四种隔离级别
  • 支持行级锁及外键约束:因此可以支持写并发;
  • 不存储总行数;
  • 一个InnoDb引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为2G),受操作系统文件大小的限制;
  • 主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整。

两者的适用场景:

因为MyISAM相对简单所以在效率上要优于InnoDB.如果系统读多,写少。对原子性要求低。那么MyISAM最好的选择。且MyISAM恢复速度快。可直接用备份覆盖恢复。

如果系统读少,写多的时候,尤其是并发写入高的时候。InnoDB就是首选了。

2、索引

普通索引: 没有任何限制条件的索引,该索引可以在任何数据类型中创建。

唯一索引: 使用UNIQUE参数可以设置唯一索引。创建该索引时,索引列的值必须唯一,但允许有空值。通过唯一索引,用户可以快速地定位某条记录,主键索引是一种特殊的唯一索引。

全文索引: 仅可用于 MyISAM 表,针对较大的数据,生成全文索引耗时耗空间。

空间索引: 只能建立在空间数据类型上。这样可以提高系统获取空间数据类型的效率。仅可用于 MyISAM 表,索引的字段不能为空值。使用SPATIAL参数可以设置索引为空间索引。

单列索引: 只对应一个字段的索引。

多列索引: 在表的多个字段上创建一个索引。该索引指向创建时对应的多个字段,用户可以通过这几个字段进行查询,想使用该索引,用户必须使用这些字段中的一个字段。


  • 聚集索引,将无序的数据转为有序的B+树,索引主要有B+树和hash两种类型,hash会出现哈希冲突,适合等值查询,不适合范围查询,容易发生冲突。另外还有数组适合做静态存储引擎的索引。对于B+树来说,叶子结点存储的是真实的数据,其他节点都是为了叶子结点数据查找做准备。且是按照值得到小放在叶子结点上,各叶子节点之间通过双向链表进行连接,索引对应的是页 -- B+树索引找到的只是被查找的数据行所在的页,然后数据库通过把页读入内存,再在页中进行查找,找到对应的数据。叶子结点存放的是一整行的数据。每一张表只有一个聚集索引
  • 辅助索引:辅助索引存放的则是对应的主键,其中辅助索引会导致的问题是回表查询
  • 索引的操作: create创建| show 查看| alter 删除
select * from user where age = 28  //先查找辅助索引age,在查找对应的主键索引id
可以创建联合索引,进行覆盖查询
create index age_name on use('age',name);
  • 最左前缀原则 查询联合索引的最左边的字段 原则则是经常使用的放在最左边,加快查询的速度

缺点:顺序依赖 比如 a,b,c 其中a,b则依赖于a,b,c | 如果是b,c则不需要

  • 分析:通过explain语句进行分析

  • 一般什么情况下加索引,什么情况下不加索引?

  1. 写操作比较频繁的操作慎重加索引
  2. 不要为输出的列添加索引,而是在选择的条件上
select ip_address from t_user_action_log
where name='LiSi'
group by action
order by create_time;

其中在name、action、create_time条件上加,而不是在ip_address
  • 索引下推 对于联合索引来说,如果查询中某个列的范围查询,则右边的锁对应的列都无法使用索引进行查询,因此退出索引下推。当使用联合索引的时候,如果左侧索引存在范围查询,则一边使用索引进行查询,一边where过滤

3、事务(对应的InNoDB引擎才有事务)

事务的四个特性:ACID 原子性,持久性、一致性、隔离性

并发访问的时候,将会导致以下的问题,脏读,不可重复读(数据的修改)、幻读(数据的增加或减少

基于以上的问题,提出了四种的隔离级别:未提交读,提交读、可重复读、可串行化。 对应的事务的隔离级别越高,并发一致性的问题就越少,但是数据库付出的代价就越高

四种隔离级别的具体的实现:MVCC(版本一致性),其中MVCC包括undolog和readview

Undolog 版本链,记录事务如何回到之前视图记录的状态

readview 视图 对于某一个事务来说,能看见哪些undolog

3.1 隔离级别的具体实现(MVCC),主要是已提交读和可重复读

  • 对于已提交读的情况下,视图是在每个SQL语句下进行创建的
  • 在可重复读的情况下,视图是在事务启动的时候就创建,即一个事务在启动的执行过程中数据是一致的

在InnoDB中,会在每行数据后添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。

1.已经执行完那么多操作,如何回到视图记录的状态?
使用undolog版本连,InnoDB根据undolog得到数据的历史版本,同一条记录在系统中存在多个版本,就是数据库中的多版本并发控制
2. 每条记录如何和undolog进行关联呢?
有两个字段,最新更新事务的ID,之前生成的undolog的指针,将undolog进行串联起来 3.一个记录被一堆事务进行修改,一个记录就会有很多的undolog,怎么保证事务能看见哪些undolog?
ReadView机制就是用来判断当前事务能够看到哪些版本

通过undolog版本链,和readview视图机制,可以保证一个事务不会读到并发执行的另一个事务的更新,但可以读到事务自己修改的数据或事务之前的数据

事务的来讲主要是针对不可重复读的隔离级别,在事务一开始的时候生成视图来控制能读到的版本连。这时的MVCC包括readview和undolog来实现提交读和可重复读的隔离级别

对应的幻读的实现,可利用可串行化实现(更高的隔离级别),每次操作都进行加锁
对于低的隔离级别,不可重复读,使用MVCC版本控制进行实现,分为快照读和当前读。对于快照读,则使用MVCC就可以。对于当前读,使用MVCC加邻键锁

四、锁机制

INNODB随时都可以进行加锁,但不是随时进行解锁,采用两阶段所协议,只有在commit和rollback时才可以进行解锁

加锁:意向锁 表锁 行锁(基于索引的,因为索引就是一行行的数据)

INNODB存储引擎行锁的三种算法 分为一个索引和多个索引

  • Record Lock:记录锁 封锁该行的唯一索引记录 加for update
  • next-key Lock:邻键锁
  • Gap lock:间隙锁 基于非唯一索引,是一段范围内索引进行加锁 bettwen 1 and 10 for update

五、日志 主要是redo log 和 bin log日志 还有undolog日志进行实现MVCC,回滚

  • binlog InnoDB存储引擎持有,记录DB执行的写入性操作,以二进制的形式保存在磁盘中
写入的方式:追加  类似于redis中的AOF

//待补

补:问题 慢查询的优化

  1. 分析语句:是否加载了额外的数据
  2. explain获得索引的使用情况,使语句可能命中更多的索引
  3. 是否数据量过大,是否分库分表