mysql相关梳理

mysql是如何实现事务的
数据库事务性的确保:ACID机制

  • 原子性(A):undo(回滚日志)
  • 一致性(C):
  • 隔离性(I):四个隔离级别(InnoDB默认使用可重复读)
  • 持久性(D):通过redo(重做日志)

读写分离何时强制要读主库,读哪个从库是通过什么方式决定的,从库的同步mysql用的什么方式

  • 读写在同一事务,或者读取数据要求无延迟,则一定要读主库;
  • 从库与主库间通过binlog 同步

问:如何优化mysql的查询?

  • 优化mysql查询缓存,提升命中率(如使用变量替代函数)
  • 通过EXPLAIN查看分析处理流程,找出性能瓶颈并优化
  • 优化索引
  • 尽可能使用not null(NULL仍然需要额外空间,并且在比较时程序会更复杂)
  • 对大数据表做拆分(垂直、水平)
  • 考虑使用本地缓存+mysql优化热点数据查询
  • 对一些特殊的特点数据,可以先离线统计出来放入前置缓存查询,避免查询瓶颈(如买家库中的大卖家)

问:mysql的索引主要有哪几种?

  • 主要有B+树索引和哈希索引等

索引在数据库中有什么作用?

  • 加快数据查询(减少扫描数据量、避免服务器的排序和临时表、将随机IO转为顺序IO)
  • 索引是对数据表中一或多个列进行排序的结构。与搜索所有行相比,索引用指针指向存储(在表中指定列)的数据,然后根据指定次序排列这些指针,有助于更快获取信息。索引将占用磁盘空间,影响数据更新速度,但多数情况下索引带来的速度优势大大超过不足。
  • 主键、二级索引、覆盖索引

使用索引时的注意点

  • 索引会大大提高检索速率,但也降低更新速率,因为需要额外更新索引
  • 索引不会包含有NULL的列(数据库设计时不要让字段默认值为NULL)
  • 索引要精短(节省存储,提升效率),对于长的索引字段可使用前缀截取
  • like操作不推荐,使用的话,"%aaa%"不会使用索引,"aaa%"可以使用索引(最左前缀)
  • 多列索引时,要将选择性最高的列放最前面,但需要排序操作时排序字段一般最优先索引

问题:使用索引一定能提升性能吗?

  • 索引需要存储空间,所以也不是越多越好,如果引入索引的成本比不用索引增加的成本更大,就最好不用索引
  • 如果数据表中数据少,没有必要创建索引
  • 修改的性能明显多于检索时,建议少创建索引,因为索引会增加修改的成本

问:B+树索引和哈希索引有何优劣?

  • B+树索引是innoDB引擎默认的索引方式,检索和更新复杂度为O(logN)(与树的高度相关),可以支持范围查询

  • 哈希索引基于哈希表,只支持单值的查询更新,但是效率很高,复杂度为O(1),适合特定离散的热点数据做索引,innoDB引擎实现了自适应哈希索引,如果发现特定数据满足热点数据条件就自动为其创建哈希索引

  • 为什么默认使用B+树实现索引?
    索引往往以文件形式存储在磁盘,索引查找就要产生磁盘I/O,评价索引优劣最重要指标就是查找过程磁盘I/O次数。
    B-Tree中一次检索最多需要h-1次I/O(根节点常驻内存),渐进复杂度为O(logmN)。一般m非常大,因此h非常小(通常不超过3)。
    综上,用B-Tree作为索引结构效率非常高。

问:B+树的结构有什么特点?

  • (1)每个父节点元素都会出现在子节点中,且为子节点的最大或最小元素
  • (2)叶子节点包含所有的数据元素的关联信息,其他节点仅为索引,没有数据关联
  • (3)每个叶子节点都有指针指向下一节点,形成一个有序链表。

问:Mysql的聚集索引和非聚集索引有何区别?

  • 聚集索引是按表中主键改构造的一个B+树,每张表只有一个聚集索引(对应一个主键),索引叶子节点即为对应的数据节点,因此InnoDB表数据文件本身就是聚集索引。聚集索引对于按主键的排序和范围查找非常快。
  • 非聚集索引即辅助索引,一个表可以有多个,通过该索引查找时先遍历索引通过叶指针获得指向聚集索引的主键,然后通过聚集索引查找完整数据(两次检索)。
  • 为什么不建议使用过长字段做主键?
    因为所有辅助索引都引用主索引,过长的主索引会令辅助索引变得过大。
  • 为什么经常使用自增字段做主键?
    因为InnoDB数据文件本身是一颗B+Tree,非单调主键会造成插入新记录时数据文件为维持B+Tree特性而频繁分裂调整,十分低效,而使用自增字段作主键则是好选择。

为什么非聚集索引要存储指向聚集索引的主键,而不是直接存储节点的物理地址?(这样可以少一次指针查询)

  • 是由B+树的索引结构决定的,B+树在插入数据时会出现页分裂,如果在中间位置分裂,而后面所有节点的物理地址都会改变,这样直接存物理地址的更新成本是无法接受的。

问:Mysql在并发事务中可能产生哪些问题?

  • (1)脏读:事务A读取到了B的更新数据,如果B回滚的话,A读到的成为脏数据
  • (2)不可重复读:事务B在A多次读取同一数据时对该数据做更新提交导致A读取的数据前后不一致(侧重于修改)
  • (3)幻读:类似不可重复读,不过是在过程中对数据做了增或删。

问:Mysql的事务隔离层级有哪几种?可以解决以上哪些并发问题?

  • (1)读未提交:3个都没解决
  • (2)读已提交(RC级别):解决脏读问题
  • (3)可重复读(RR级别,InnoDB默认):解决脏读和不可重复读问题
  • (4)串行化:解决全部问题,但性能差
  • InnoDB默认使用层级(3),并通过优化策略解决了幻读问题

问:InnoDB通过什么策略解决了幻读问题,同时又保证性能?

  • Mysql的MVCC保证高并发性能,使用next-key lock解决幻读问题
  • 对于简单读(简单select),不用加锁(读取记录的快照版本)
  • 对于当前读(增删改,这些操作需要先获取最近版本数据,然后进一步操作),需要加锁-(next-key lock)(读取记录的最新版本)

问:InnoDB在当前读时是如何加锁的?

  • 如果表中只有一个聚集索引,那么只会对直接命中的行加锁
  • 如果表中同时存在非聚集索引,需要加GAP锁,确保在多次读取之间其他事物不会插入新的满足条件的记录并提交。

问:InnoDB引擎有哪些关键特性?

  • (1)插入缓冲(Insert Buffer):在非聚集索引插入或更新时,不直接插入到索引ye ,而是先判断索引页是否在缓冲池,在的话直接插入,不在则放入一个Inset Buffer对象;然后再以一定频率进行Buffer和索引页节点的merge。这样大大提升了非聚集索引插入更新的性能。

  • (2)双写(提高数据可靠性)由doubleWriter buffer和磁盘共享空间组成,做脏页刷新时先写buffer然后同步共享空间(连续存储,效率高),之后再将buffer数据写到表文件。如果写表过程中崩溃,引擎先从共享空间中找到该页的副本,复制到表空间文件,然后使用重做日志恢复数据。

  • 问:为什么不直接使用重做日志恢复数据?

  • 答:因为重做日志记录的是页的物理操作,如果页本身损坏是无法重做的,因此重做之前需要一个页的副本做基准。

  • (3)自适应哈希索引:监控索引页查询,如果发现建立哈希索引可以提升性能,即创建之(自动创建)。

  • (4)异步IO:提升磁盘操作性能,可以支持IO的merge。

  • (5)刷新临接页:刷新脏页时,同时判断该页所在区所有页,如果为脏页一并刷新。

问: mysql中的binlog、redo log、undo log有何区别?

  • binlog:是MySQL Server层记录的日志,是逻辑日志,不支持并发,用于数据恢复、主从复制等
  • redo log(重做日志):InnoDB引擎记录的日志,是物理日志(速度比逻辑日志快很多,所以InnoDB优先使用redo log而不是binlog),支持并发,作用同binlog,用来保证事务的原子性和持久性。包含重做日志缓冲和重做日志文件(异步刷写)
  • undo log:为实现事务一致性的日志,数据操作前先备份数据到undo log,如果事务执行中出错或rollback,可使用log中的备份将数据恢复到原有状态。

问:怎么通过binlog完成数据恢复?

  • 先通过mysqlbinlog命令恢复binlog日志并导入文件
  • 然后通过source命令导入数据表中

mysql如何完成主从同步

  • 通过binlog追赶

  • 精卫中间件:解析binlog,转为MQ消息发给备库,备库消费消息完成同步,消息中间件提供消息有序性的保证(可靠可重试,异步松耦合,扩展性好,吞吐量大)

>>InnoDB的一致性读是怎么实现的?需要加锁吗?

  • 默认情况下使用一致性非锁定读,不加锁
  • 一些情况下可以在读取时显式加锁以保证逻辑一致性 select … for update

>>如何解决多并发导致的死锁问题?

  • (1)为每个事务设置超时时间,超时自动回滚某个或某些事务;(2)执行死锁检测(状态图),检测到死锁后回滚某些事务以消除循环依赖(一般回滚undo链路短的事务–回滚成本低)

什么是聚集索引?有哪些好处?又有哪些潜在的问题
把数据行和索引(主键)紧凑存储在一起,一个数据表文件其实就是一个聚集索引

好处

  • 通过主键的精准和范围查询效率很高

问题

  • 插入性能依赖于插入顺序,因此要求主键为顺序递增
  • 更新聚集索引的代价高,会强制将每个被更新的行移动到新位置
  • 插入新行可能导致页分裂问题(主键不连续的话)
  • 可能造成二级索引比想象中大,因为二级索引叶子需要包含主键(要求主键字段尽可能短小)
  • 造成二级索引查询需要两次索引查找(查询主键值+查询主键对应的行)

如何避免二级索引的第二次索引查找—使用覆盖索引

如何使用索引排序–让索引的次序和order by子句顺序完全一致,并且所有列的排序方向都一致

Mysql的主从同步(复制)有哪几种方式?

  • 基于语句的复制
  • 基于行的复制

开放题目:分库分表

常见的分库分表方式有哪些?

  • 根据业务字段取模分表(需要迁移数据)
  • 一致性哈希分表(支持动态扩展)
  • 雪花算法生成全局ID分表(支持动态扩展)(最高位始终为0----41位的时间序列,精确到ms,可以根据时间排序----10位机器标识,最多支持部署1024个节点----12位计数序列号(自增id),12位的计数序列号支持每个节点每毫秒产生4096个ID序号。)

一致性哈希的原理是什么?

  • 把节点对应哈希值变成一个范围而不再是离散的,如果有节点加入会从原来某个节点分管一部分范围的哈希值。
  • 新增一个节点,只有一个其他节点会受影响—问题:造成负载不均衡
  • 改进:引入虚拟节点,一个物理节点对应多个虚拟节点,可以均匀插入哈希环中。这样增减物理节点相对会增减很多虚拟节点,确保负载相对均衡。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章