1. MySQL中innodb和myisam的区别

  1. myisam是5.1之前的默认引擎,支持全文检索、压缩、空间函数等。
    1. mysiam不支持事务和行级锁,所以一般用于大量查询和少量插入的场景使用
    2. mysiam不支持外键,并且索引和数据是分开存储的
  2. innodb是基于聚簇索引建立的

    1. innodb支持事务,外键
    2. 通过MVVC来支持高并发,索引和数据存储在一起
    3. MVVC(Multi-Version Concurrency Control)多版本的并发控制协议

      2. MySQL的索引有哪些,聚簇和非聚簇索引又是什么

  3. 索引按数据结构划分为:B+树和hash索引

    1. B+树是左小右大的顺序存储结构,节点只包含id索引列,而叶子节点包含索引列和数据,这种数据和索引在一起存储的索引方式叫做聚簇索引。一张表只能有一个聚簇索引。
    2. 假设没有定义主键,innodb会选择一个唯一的非空索引来替代,如果没有的话则会隐式指定一个主键作为聚簇索引。
    3. innodb中,在聚簇索引之上创建的索引称之为辅助索引,辅助索引访问数据总是需要二次查找。辅助索引叶子节点上存储的不再是行的物理位置,而是主键值。
  4. 非聚簇索引
    1. 将数据存储与索引分开结构,索引结构的叶子节点指向了数据的对应行,myisam通过key_buffer把索引先缓存到内存中,当需要访问数据时(通过索引访问数据),在内存中直接搜索索引,然后通过索引找到磁盘相应数据。这也就是为什么索引不在key_buffer命中时,速度慢的原因。

image.png

3. 覆盖索引和回表

  1. 覆盖索引

    1. 在一次查询中,如果一个索引包含或者覆盖所有需要查询的字段的值,我们称之为覆盖索引,而不再需要回表查询
    2. 要确定一个查询是否是覆盖索引,我们只需要explain sql语句看Extra的结果是否是“Using index”即可。

      4. 锁的类型有哪些

  2. MySQL的锁分为表锁和行级锁,也叫做读锁和写锁

    1. 读锁是共享的,可以通过lock in share mode实现,这时候只能读不能写
    2. 写锁是排它锁,他会阻塞其他的写锁和读锁。从颗粒度来区分,可以分为表锁和行锁。
  3. 写锁

    1. 表锁会锁定整张表并且阻塞其他用户对该表的所有读写操作,比如alter修改表结构的时候会锁表。
    2. 行锁又可分为乐观锁和悲观锁
      1. 悲观锁通过for update实现
      2. 乐观锁通过版本号实现

        5. 事务的基本特性和隔离级别

        事务的基本特性是ACID
  4. A:原子性

    1. 一个事务的操作要么全部成功,要么全部失败
  5. C:一致性
    1. 一个事务执行前后,数据库的完整性约束没有被破坏
  6. I:隔离性
    1. 当多个用户并发访问数据库时,比如同时访问一张表,数据库每一个用户开启的事务不能被其他事务所作的操作干扰,多个并发事务之间,应当相互隔离
  7. D:持久性
    1. 事务执行成功后,该事务对数据库的更爱是持久地保存在数据库中过的

隔离性有四个级别

  1. read uncommit 读未提交,可能会读到其他事务未提交的数据,也叫脏读。
    1. 用户本来应该读到id=1的用户age应该是10,结果读到了其他事务还没有提交的事务,结果读到结果age=20,这就是脏读。
  2. read commit 读已提交,两次读取结果不一样,叫做不可重复读。
    1. 不可重复读解决了脏读的问题,他只会读取已经提交的事务。
    2. 用户开启事务读取id=1用户,查询到age=10,再次读取发现结果=20,在同一个事务里同一个查询读取到不同的结果叫做不可重复读。
  3. repeated read 可重复读,这是MySQL的默认级别,就是每次读取结果都不一样,都是有可能产生幻读
  4. serializable 串行,一般不会使用,他会给每一行读取的数据加锁,会导致大量超时和锁竞争问题。

    6. ACID靠什么保证

  5. A原子性:是undo log日志保证的,他记录了需要回滚的日志信息,事务回滚时撤销已经执行成功的sql

  6. C一致性:一般由代码层面保证
  7. I隔离性:由MVCC来保证
  8. D持久性:由内存和redo log保证,MySQL修改数据同时在内存和redo log 记录这次操作,事务提交的时候通过redo log 刷盘,宕机的时候可以从redo log恢复。

    7. 什么是幻读,什么是MVCC

  9. 要说幻读,首先要了解MVCC,MVCC叫做多版本并发控制,实际上就是保存了数据在某个时间节点的快照。

  10. 我们每行数实际上隐藏了两列,创建时间版本号,过期(删除)时间版本号,没开始一个新的事务,版本号都会自动递增。

  11. 8. 什么是间隙锁

  12. 间隙锁是可重复读级别下才有的锁,结合MVCC 和间隙锁可以解决幻读的问题。

9. 分库分表是怎么做的

分库分表分为垂直和水平两个方式,拆分的顺序是先垂直后水平。

  1. 垂直分库
    1. 订单 用户 商品 支付 预算
  2. 垂直分表
    1. 如果表字段比较多,将不常用的、数据较大的等等做拆分
    2. 把订单表分为基础信息、订单扩展和收货地址
  3. 水平分表

    10. 分表后的id怎么保证唯一性的

    因为我们的主键默认是自增的,那么分表之后的主键在不同的表中肯定会有冲突。几个解决方法如下:

  4. 设定步长,比如1-1024张表我们分别设定1-1024的基础步长,这样主键落到不同的表就不会冲突了。

  5. 分布式ID,自己实现一套分布式ID生成算法或是使用开源的比如雪花算法
  6. 分表后不使用主键作为查询依据,而是每张表单独新增一个字段作为唯一主键使用,比如订单表订单号是唯一的,不管最终落在哪张表都是基于订单号作为查询依据,更新也一样。

    11. MySQL主从同步是怎么做的

    MySQL主从同步的原理

  7. master提交事务后,写如binlog

  8. slave 连接到master,获取binlog
  9. master创建dump线程,推从binlog到slave
  10. slave启动一个IO线程读取同步过来的master的binlog,记录到relay log中继日志中
  11. slave 记录自己的binlog

image.png
MySQL默认的复制方式是异步的,主库把日志发送从库后就不关心是否已经处理,这样这样会产生一个问题就是假设主库挂了,从库处理失败了,这时候从库升为主库,日志就丢失了。两个方法:

  1. 全同步复制
    1. 主库写入binlog后强制同步日志到从库,所有的从库都执行完成后才返回给客户端,这个性能会受到影响
  2. 半同步复制
    1. 从库写入日志成功后返回ACK确认给主库,主库收到至少一个从库的确认就认为写操作完成