1. InnoDB和MyISAM的区别

  1. InnoDB支持行级锁和表级锁,默认为行级锁,MyISAM只支持表级锁。
  2. MyISAM不支持事务。而InnoDB属于事务型引擎,支持事务、回滚以及崩溃修复能力。
  3. MyISAM不支持外键,而InnoDB支持外键。
  4. InnoDB支持多版本并发控制(MVCC),可以在RC和RR两种隔离级别下工作。
  5. InnoDB索引组织方式为聚簇索引,主键索引B+树叶子节点中存放的就是数据,辅助索引B+树叶子结点中存放的是对应记录的主键,而MyISAM索引组织方式为非聚簇索引,其数据和索引是分离的,B+树叶子结点data域中存储的是对应行的指针地址。
  6. InnoDB不保存表的具体行数,执行count(*)时会进行全表扫描,而MyISAM使用一个变量存放整个表的行数,没有where子句时查询很快。
  7. InnoDB不支持全文索引,而MyISAM支持全文索引。
  • 如何选择合适的引擎,需要考虑哪些因素?
    • 是否需要支持事务
    • 绝大多数操作为查询时可以使用MyISAM
    • 是否需要崩溃修复能力
  • 为什么InnoDB推荐自增ID作为主键?
    • InnoDB引擎的插入性能严重依赖插入顺序,而按照主键的顺序插入时最快的方式,自增ID可以保证每次B+索引是从右边扩展的,可以避免B+树频繁的合并和分裂。
  • InnoDB四大特征:插入缓冲,二次写,自适应哈希索引,预读

2. 什么是池化思想,什么是数据库连接池,为什么要使用数据库连接池?

  • 通俗地理解,池化思想就是将所有资源聚集到一起统一地进行管理。
  • 数据库连接池的本质是一个socket的连接。将这些连接对象存储在内存中,当需要访问数据库时,优先从连接池中取出一个空闲的连接供用户使用,当访问结束时,这个连接也并不一定会关闭,而是将其归还连接池,共给接下来的用户使用,连接的建立销毁都由连接池来管理。
  • 使用数据库连接池增强了连接的复用能力,将连接统一管理,减少管理成本,在使用时无需重新建立连接,加快响应速度,控制并发数量,减少系统崩溃的可能性。

3. 说说count(1),count(*),count(列名)的区别?

  • count(1)包括了所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL ;count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL ,count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计
  • 效率比较 count(*) > count(1) > count(主键) > count(列名)

4. MySQL如何保证数据的一致性?增删改语句是如何执行的?

以InnoDB引擎为例说明:

MySQL自带一个日志模块BinLog(归档日志),InnoDB自带一个日志模块redo Log(重做日志),

比方说,我们现在将一条数据进行了修改update table set username = 'lyp' where id = 1;

  1. 首先这条语句会经过分析器、优化器、执行器确认好执行计划,从表中查询到id为1的这条数据
  2. 拿到这条语句,将username字段修改为lyp,接着调用存储引擎API,将数据保存在内存中,同时记录redo log此时这条redo log的状态为prepare,意思是预提交,但是还没有真正提交,然后通知执行器,可以进行提交操作了。
  3. 执行器收到通知后,记录binlog,然后调用引擎接口,将刚刚记录的redolog状态设置为提交。
  4. 执行完成

可以看出两个日志模块的记录逻辑是:redo log预提交=》binlog记录=》redolog提交

考虑两个场景:

  1. 先记录binlog,后记录redolog:当写完binlog,还未写redolog时系统异常退出,由于没有redolog,本机无法恢复这一条记录,而binlog中又存在这条记录,数据不一致
  2. redolog直接提交,后写binlog:当提交redolog后还未写binlog时系统异常退出,系统在恢复记录时会根据redolog将这条数据恢复,但是这条数据在binlog中是不存在的,也会数据不一致

5. MySQL的持久化机制

  • 数据库在进行持久化存储时并不会直接对数据进行修改,而是使用“事务日志”,存储引擎在修改表的数据时只修改其内存拷贝,再把这种修改行为记录到持久在硬盘上的事务日志中,事务日志持久之后,内存中的被修改的数据可以慢慢刷回到磁盘,这叫做“预写式日志”,修改数据需要写两次磁盘。
  • 具体以InnoDB为例,当有记录需要更新时,InnoDB会将记录写到redo log中,并更新内存,这是就更新完成了。同时InnoDB会在机器空闲的时候将这个操作记录更新到磁盘中。
  • redo 日志会把事务在执行过程中对数据库所做的所有修改都记录下来,在之后系统崩溃重启后可以把事务所做的任何修改都恢复出来
  • redo log占用空间小,而且是顺序写入磁盘

6. MySQL的主从复制

  1. 主库将事务操作记录到二进制日志binlog
  2. 从库通过一个I/O线程以正常地方式连接到主库,从主库上读取二进制日志,并写入从库的中继日志Relay log
  3. 从库开启一个SQL线程,从从库的中继日志中读取时间并重放(执行),使得从库的数据与主库中的数据一致。
  • 要注意的是,在主库上并行更新的操作不能在从库上并行执行,一定是串行化的
  • 读写分离
    • 主服务器处理写操作以及实时性要求比较高的读操作,而从服务器处理读操作。
    • 读写分离能提高性能的原因在于:
      • 主从服务器负责各自的读和写,极大程度缓解了锁的争用;
      • 从服务器可以使用 MyISAM,提升查询性能以及节约系统开销;
      • 增加冗余,提高可用性。