欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

Mysql

最编程 2024-01-18 10:23:50
...

https://zhuanlan.zhihu.com/p/470218900

1、数据库

1.4 数据库三大范式

第一范式(1NF):每个列都不可以再拆分,强调的是列的原子性。第一范式要求数据库中的表都是二维表。
第二范式(2NF):在第一范式的基础上,一个表必须有一个主键,非主键列 完全依赖 于主键,而不能是依赖于主键的一部分。
第三范式(3NF):在第二范式的基础上,非主键列只依赖(直接依赖)于主键,不依赖于其他非主键。

1.5 数据库连接泄露的含义

数据库连接泄露指的是如果在某次使用或者某段程序中没有正确地关闭 Connection、Statement 和 ResultSet 资源,那么每次执行都会留下一些没有关闭的连接,这些连接失去了引用而不能得到重新使用,因此就造成了数据库连接的泄漏。数据库连接的资源是宝贵而且是有限的,如果在某段使用频率很高的代码中出现这种泄漏,那么数据库连接资源将被耗尽,影响系统的正常运转。

2、索引

索引本质上就是一种通过减少查询需要遍历行数,加快查询的数据结构。

2.1 索引的优缺点:

(1)索引的优点:

  • 减少查询需要检索的行数,加快查询速度,避免进行全表扫描,这也是创建索引的最主要的原因。
  • 如果索引的数据结构是B+树,在使用分组和排序时,可以显著减少查询中分组和排序的时间。
  • 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。
    (2)索引的缺点:
  • 当对表中的数据进行增加、删除和修改时,索引也要进行更新,维护的耗时随着数据量的增加而增加。
  • 索引需要占用物理空间,如果要建立聚簇索引,那么需要的空间就会更大。
2.2 索引的使用场景:

(1)在哪些列上面创建索引:

  • WHERE子句中经常出现的列上面创建索引,加快条件的判断速度。
  • 按范围存取的列或者在group by或order by中使用的列,因为索引已经排序,这样可以利用索引加快排序查询时间。
  • 经常用于连接的列上,这些列主要是一些外键,可以加快连接的速度;
  • 作为主键的列上,强制该列的唯一性和组织表中数据的排列结构;
    (2)不在哪些列建索引?
  • 区分度不高的列。由于这些列的取值很少,例如性别,在查询的结果中,结果集的数据行占了表中数据行的很大比例,即需要在表中搜索的数据行的比例很大。增加索引,并不能明显加快检索速度。
  • 在查询中很少的列不应该创建索引。由于这些列很少使用到,但增加了索引,反而降低了系统的维护速度和增大了空间需求。
  • 当添加索引造成修改成本的提高 远远大于检索性能的提高时,不应该创建索引。当增加索引时,会提高检索性能,但是会降低修改性能。当减少索引时,会提高修改性能,降低检索性能。
  • 定义为text, image和bit数据类型的列不应该增加索引。这些列的数据量要么相当大,要么取值很少。
2.3 索引的分类:

(1)普通索引、唯一索引、主键索引、全文索引、组合索引。

普通索引:最基本的索引,没有任何限制
唯一索引:但索引列的值必须唯一,允许有空值,可以有多个NULL值。如果是组合索引,则列值的组合必须唯一。
主键索引:一种特殊的唯一索引,不允许有空值。
全文索引:全文索引仅可用于 MyISAM 表,并只支持从CHAR、VARCHAR或TEXT类型,用于替代效率较低的like 模糊匹配操作,而且可以通过多字段组合的全文索引一次性全模糊匹配多个字段。
组合索引:主要是为了提高mysql效率,创建组合索引时应该将最常用作限制条件的列放在最左边,依次递减。

(2)聚簇索引与非聚簇索引:
如果按数据存储的物理顺序与索引值的顺序分类,可以将索引分为聚簇索引与非聚簇索引两类:

聚簇索引:表中数据存储的物理顺序与索引值的顺序一致,一个基本表最多只能有一个聚簇索引,更新聚簇索引列上的数据时,往往导致表中记录的物理顺序的变更,代价较大,因此对于经常更新的列不宜建立聚簇索引
非聚簇索引:表中数据的物理顺序与索引值的顺序不一致的索引组织,一个基本表可以有多个聚簇索引。

聚簇索引一般在下面场景使用:
(1)主键列,InnoDB存储引擎中,默认为表的主键建立一个聚簇索引。
(2)按范围存取的列或者在group by或order by中使用的列。在聚簇索引下,因为表中数据存储的物理顺序与索引的逻辑顺序一致,所以在包含范围检查(between、<、<=、>、>=)或使用group by或order by的查询时,一旦找到具有范围中第一个键值的行,具有后续索引值的行保证物理上毗连在一起而不必进一步搜索,避免了大范围扫描,可以大大提高查询速度。
(3)在连接操作中使用的列。
(4)不经常修改的列。因为码值修改后,数据行必须移动到新的位置。

2.4 索引的数据结构:

常见的索引的数据结构有:B+Tree、Hash索引。

hash索引的缺点:

  • Hash索引仅能满足等值的查询,不能满足范围查询、排序。因为数据在经过Hash算法后,其大小关系就可能发生变化。
  • 当创建组合索引时,不能只使用组合索引的部分列进行查询。因为hash索引是把多个列数据合并后再计算Hash值,所以对单独列数据计算Hash值是没有意义的。
  • 当发生Hash碰撞时,Hash索引不能避免表数据的扫描。因为仅仅比较Hash值是不够的,需要比较实际的值以判定是否符合要求。
  • Hash 索引不支持模糊查询以及多列索引的最左前缀匹配,原理也是因为 Hash 函数的不可预测。

B+Tree索引的优点:

  • 页内节点不存储内容,每次IO可以读取更多的行,大大减少磁盘I/O读取次数
  • 带顺序访问指针的B+Tree:B+Tree所有索引数据都存储在叶子结点上,并且增加了顺序访问指针,每个叶子节点都有指向相邻叶子节点的指针,这样做是为了提高区间查询效率。
2.5 什么是前缀索引

有时需要索引很长的字符列,它会使索引变大并且变慢,一个策略就是索引开始的几个字符,而不是全部值,即被称为 前缀索引

前缀索引需要的空间变小,但也会降低选择性。索引选择性(INDEX SELECTIVITY)是不重复的索引值(也叫基数)和表中所有行数(T)的比值,数值范围为 1/T ~1。高选择性的索引有好外,因为在查找匹配的时候可以过滤掉更多的行,唯一索引的选择率为 1,为最佳值。对于前缀索引而言,前缀越长往往会得到好的选择性,但是短的前缀会节约空间,所以实操的难度在于前缀截取长度的抉择,可以通过调试查看不同前缀长度的 平均匹配度,来选择截取长度。

2.6 什么是最左前缀匹配原则

在检索数据时从联合索引的最左边开始匹配。根据最左前缀匹配原则,MySQL 会一直向右匹配直到遇到 范围查询(>、<、between、like)就停止匹配。

2.7 索引失效在以下情况:
  1. 不满⾜最左【前缀】匹配规则
  2. 在索引列上做任何操作如计算、函数、(⼿动或⾃动)类型转换等操作,会导致索引失效⽽进⾏全表扫描
  3. 使⽤不等于(!= 、<>)
  4. like 中以通配符开头(’%abc’)
  5. 字符串不加单引号索引失效
  6. or 连接索引失效
2.8 为什么使用B+Tree作为索引:

索引本身也很大,不可能全部存储在内存中,因此索引往往以索引文件的形式存储在磁盘上。这样的话,索引查找过程中就要产生磁盘I/O消耗,相对于内存存取,磁盘I/O存取的消耗要高几个数量级。

(1)B+树有利于对数据库的扫描:B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题,而B+树只需要遍历叶子节点就可以解决对全部关键字信息的扫描,所以范围查询、排序等操作,B+树有着更高的性能。
(2)B+树的磁盘IO代价更低:B+树的内部结点的data域并没有存储数据,因此其内部结点相对于B树更小。如果把所有同一内部结点的关键字存放在同一盘块中,那么盘块所能容纳的关键字数量也越多。一次性读入内存中的需要查找的关键字也就越多,相对来说I/O读写次数也就降低了。
(3)B+树的查询效率更加稳定:由于B+树的内部结点只是叶子结点中关键字的索引,并不存储数据。所以任何关键字的查找必须走一条从根结点到叶子结点的路。所有关键字查询的路径长度相同,导致每一个数据的查询效率相当。
https://blog.****.net/a745233700/article/details/114242960

2.9 索引优化:

在这里插入图片描述

3、常用的存储引擎?InnoDB与MyISAM的区别?

在这里插入图片描述
存储引擎是对底层物理数据执行实际操作的组件,为Server服务层提供各种操作数据的API。常用的存储引擎有InnoDB、MyISAM、Memory。这里我们主要介绍InnoDB 与 MyISAM 的区别:
(1)事务:MyISAM不支持事务,InnoDB支持事务
(2)锁级别:MyISAM只支持表级锁,InnoDB支持行级锁和表级锁,默认使用行级锁,但是行锁只有通过索引查询数据才会使用,否则将使用表锁。行级锁在每次获取锁和释放锁的操作需要消耗比表锁更多的资源。使用行锁可能会存在死锁的情况,但是表级锁不存在死锁
(3)主键和外键:MyISAM 允许没有任何索引和主键的表存在,不支持外键。InnoDB的主键不能为空且支持主键自增长,如果没有设定主键或者非空唯一索引,就会自动生成一个6字节的主键,支持外键完整性约束
(4)索引结构:MyISAM 和 InnoDB 都是使用B+树索引,MyISAM的主键索引和辅助索引的Data域都是保存行数据记录的地址。但是InnoDB的主键索引的Data域保存的不是行数据记录的地址,而是保存该行的所有数据内容,而辅助索引的Data域保存的则是主索引的值。

由于InnoDB的辅助索引保存的是主键索引的值,所以使用辅助索引需要检索两遍索引:首先检索辅助索引获得主键,然后用主键到主索引中检索获得记录。这也是为什么不建议使用过长的字段作为主键的原因:由于辅助索引包含主键列,所以,如果主键使用过长的字段,将会导致其他辅助索变得更大,所以争取尽量把主键定义得小一些。

(5)全文索引:MyISAM支持全文索引,InnoDB在5.6版本之前不支持全文索引,5.6版本及之后的版本开始支持全文索引
(6)表的具体行数:
MyISAM:保存有表的总行数,如果使用 select count() from table 会直接取出出该值,不需要进行全表扫描。
InnoDB:没有保存表的总行数,如果使用 select count() from table 需要会遍历整个表,消耗相当大。
(7)存储结构:
① MyISAM会在磁盘上存储成三个文件:.frm文件存储表定义,.MYD文件存储数据,.MYI文件存储索引。
② InnoDB:把数据和索引存放在表空间里面,所有的表都保存在同一个数据文件中,InnoDB表的大小只受限于操作系统文件的大小,一般为2GB。
(8)存储空间:
① MyISAM:可被压缩,存储空间较小。支持三种不同的存储格式:静态表(默认,但是注意数据末尾不能有空格,会被去掉)、动态表、压缩表。
② InnoDB:需要更多的内存和存储,它会在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。
(9)适用场景:
① 如果需要提供回滚、崩溃恢复能力的ACID事务能力,并要求实现行锁级别并发控制,InnoDB是一个好的选择;
② 如果数据表主要用来查询记录,读操作远远多于写操作且不需要数据库事务的支持,则MyISAM引擎能提供较高的处理效率;

4、事务管理?

4.1 什么是数据库事务

数据库的事务是并发控制的基本单位,是指逻辑上的一组操作,要么全部执行,要么全部不执行。事务是保持 逻辑数据一致性 和 可恢复性 的重要利器。而锁是实现事务的关键,可以保证事务的完整性和并发性

4.2 事务的四大特性:

(1)原子性:事务是一个不可分割的工作单元,事务里的操作要么都成功,要么都失败,如果事务执行失败,则需要进行回滚。
(2)隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各个事务不干涉内部的数据。
(3)持久性:一旦事务提交,它对数据库中数据的改变就是永久的。
(4)一致性:当事务完成时,数据必须处于一致状态,多个事务对同一个数据读取的结果是相同的。

4.3 ACID的实现原理:

事务的 ACID 特性是由关系数据库管理系统来实现的。

原子性是通过MySQL的回滚日志undo log来实现的:当事务对数据库进行修改时,InnoDB会生成对应的undo log;如果事务执行失败或调用了rollback,导致事务需要回滚,便可以利用undo log中的信息将数据回滚到修改之前的样子。

持久性依靠redo log日志实现,在执行SQL时会保存已执行的SQL语句到一个redo log文件,当数据库宕机重启的时候,会将 redo log 中的内容恢复到数据库中,再根据 undo log 和 binlog 内容决定回滚数据还是提交数据。

Innodb事务的隔离级别由MVVC和锁机制实现的:
MVCC(Multi-Version Concurrency Control,多版本并发控制)用于实现读已提交和可重复读这两种隔离级别。而读未提交隔离级别总是读取最新的数据行,无需使用 MVCC。读序列化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现。

MVCC是通过在每行记录后面保存两个隐藏的列来实现的,一个保存了行的事务ID,一个保存了行的回滚段指针。每开始一个新的事务,都会自动递增产生一个新的事务ID。事务开始时会把该事务ID放到当前事务影响的行事务ID字段中,而回滚段的指针有该行记录上的所有版本数据,在undo log回滚日志中通过链表形式组织,也就是说该值实际指向undo log中该行的历史记录链表

MySQL锁机制的基本工作原理就是:事务在修改数据库之前,需要先获得相应的锁,获得锁的事务才可以修改数据;在该事务操作期间,这部分的数据是锁定,其他事务如果需要修改数据,需要等待当前事务提交或回滚后释放锁。

4.3.1、快照读在提交读和可重复读级别下有什么区别?
  1. 在RC(读已提交)级别下每次都是读取最新的快照版本
  2. 在RR(可重复读)级别下是事务开启时⽣成⼀个全局快照,后续的快照读都读取这个快照

(1)快照读(Snapshot Read) :MySQL 数据库,InnoDB 存储引擎,为了提⾼并发,使⽤ MVCC 机制,在并发事务时,通过读取数据⾏的历史数据版本,不加锁,来提⾼并发的⼀种不加锁⼀致性读。

4.4 事务的隔离级别

读未提交:允许事务在执行过程中,读取其他事务尚未提交的数据;
读已提交:允许事务在执行过程中读取其他事务已经提交的数据;
可重复读(MySQL默认级别):在同一个事务内,任意时刻的查询结果都是一致的;
读序列化:所有事务逐个依次执行,每次读都需要获取表级共享锁,读写会相互阻塞。

4.4.1 事务的并发问题

更新丢失:两个或多个事务操作相同的数据,然后基于选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题:最后的更新覆盖了其他事务所做的更新。
脏读:指事务A正在访问数据,并且对数据进行了修改(事务未提交),这时,事务B也使用这个数据,后来事务A撤销回滚,并把修改后的数据恢复原值,B读到的数据就与数据库中的数据不一致,即B读到的数据是脏数据。
不可重复读:一个事务多次读,但另一个事务在此期间修改了数据并提交,导致前后读取到的数据不一致;(修改
幻读:在一个事务中,先后两次进行读取相同的数据(一般是范围查询),但由于另一个事务新增或者删除了数据,导致前后两次结果不一致。

隔离级别 脏读 不可重复读 幻读 丢失更新
读未提交
读已提交
可重复读
可串行化
4.4.2利用锁机制解决并发问题:

排它锁解决脏读
共享锁解决不可重复读
mvcc + 临键锁解决幻读
在这里插入图片描述
在这里插入图片描述

5、锁

5.1 锁的分类

InnoDB的行锁:

  • 共享锁(S锁、读锁):可以并发读取数据,但不能修改数据。也就是说当数据资源上存在共享锁时,所有的事务都不能对该数据进行修改,直到数据读取完成,共享锁释放。
  • 排它锁(X锁、写锁):一个事务获取排它锁之后,可以对锁定范围内的数据行执行写操作,在锁定期间,其他事务不能再获取这部分数据行的锁(共享锁、排它锁),只允许获取到排它锁的事务进行更新数据。

MySQL引入了意向锁,来检测表锁和行锁的冲突
意向锁也是表级锁,分为读意向锁(IS锁)和写意向锁(IX锁)。当事务要在记录上加上行锁时,则先在表上加上对应的意向锁。之后事务如果想进行锁表,只要先判断是否有意向锁存在,存在时则可快速返回该表不能启用表锁,否则就需要等待,提高效率。

5.2 InnoDB行锁的实现与临键锁

InnoDB的行锁是通过给索引上的索引项加锁来实现的。只有通过索引检索数据,才能使用行锁,否则将使用表锁
在InnoDB中,为了解决幻读的现象,引入了临键锁(next-key)。根据索引,划分为一个个左开右闭的区间。当进行范围查询的时候,若命中索引且能够检索到数据,则锁住记录所在的区间和它的下一个区间。其实,临键锁(Next-Key) = 记录锁(Record Locks) + 间隙锁(Gap Locks)

5.3 什么是死锁?如何解决死锁

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

常见的解决死锁的方法:

  • 如果不同程序并发存取多个表,尽量约定 以相同的顺序访问表,可以大大降低死锁机会;
  • 在同一个事务中,尽可能做到 一次锁定所需要的所有资源,减少死锁产生概率;
  • 对于非常容易产生死锁的业务部分,可以尝试使用 升级锁定颗粒度,通过 表级锁 定来减少死锁产生的概率。
5.4 什么是乐观锁和悲观锁?如何实现

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作。在查询完数据的时候就把事务锁起来,直到提交事务。这对于长事务来讲,可能会严重影响系统的并发处理能力。实现方式:使用数据库中的锁机制。

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违反数据完整性。乐观锁适用于 读多写少 的应用场景,这样可以提高吞吐量。实现方式:一般会使用版本号机制或 CAS 算法实现。

6、常用的SQL语句

6.1 char与varchar的区别
  • char 表示定长字符串,长度是固定的,最多能存放的字符个数为 255,和编码无关;而 varchar
    表示可变长字符串,长度是可变的,最多能存放的字符个数为 65532;
  • 使用 char 时,如果插入数据的长度小于 char 的固定长度时,则用空格填充;
  • 因为固定长度,char 的存取速度比 varchar 快很多,同时缺点是会占用多余空间,属于空间换时间;
6.2 DROP、DELETE和TRUNCATE的区别
DROP DELETE TRUNCATE
SQL语句类型 DDL DML DDL
回滚 不可回滚 可回滚 不可回滚
删除内容 从数据库中 删除表,所有的数据行,索引和权限也会被删除 表结构还在,删除表的 全部或者一部分数据行 表结构还在,删除表中的 所有数据
删除速度 最快 速度慢,需要逐行删除 删除速度快
  • 因此,在不再需要一张表的时候,采用 DROP;
  • 在想删除部分数据行时候,用 DELETE;
  • 在保留表而删除所有数据的时候用 TRUNCATE。
6.3 UNION与UNION ALL的区别

UNION 会去重;而 UNION ALL,不去重,且效率高于 UNION。

7、MySQL主从复制的原理:

Slave从Master获取binlog二进制日志文件,然后再将日志文件解析成相应的SQL语句在从服务器上重新执行一遍主服务器的操作,通过这种方式来保证数据的一致性。由于主从复制的过程是异步复制的,因此Slave和Master之间的数据有可能存在延迟的现象,只能保证数据最终的一致性。
要实现MySQL的主从复制,首先必须打开master端的binlog (mysql-bin.xxxxxx)日志功能,否则无法实现mysql的主从复制。

7.1 主从复制的好处

(1)读写分离,通过动态增加从服务器来提高数据库的性能,在主服务器上执行写入和更新,在从服务器上执行读功能。
(2)提高数据安全,因为数据已复制到从服务器,从服务器可以终止复制进程,所以,可以在从服务器上备份而不破坏主服务器相应数据。
(3)在主服务器上生成实时数据,而在从服务器上分析这些数据,从而提高主服务器的性能。

7.2 主从复制的原理

在 Master 与 Slave 之间实现整个主从复制的过程是由三个线程参与完成的,其中有两个线程(SQL 线程和 I/O 线程)在 Slave 端,另外一个线程( I/O 线程)在 Master 端。
基本原理流程:
Master 端:打开二进制日志(binlog )记录功能 —— 记录下所有改变了数据库数据的语句,放进 Master 的 binlog 中;
Slave 端:开启一个 I/O 线程 —— 负责从 Master上拉取 binlog 内容,放进自己的中继日志(Relay log)中;
Slave 端:SQL 执行线程 —— 读取 Relay log,并顺序执行该日志中的 SQL 事件。

7.3 主从延迟要怎么解决?

1.MySQL 5.6 版本以后,提供了一种 并行复制 的方式,通过将 SQL 线程转换为多个 work 线程来进行重放
2. 提高机器配置 (王道)
3. 在业务初期就选择合适的分库、分表策略, 避免单表单库过大带来额外的复制压力
4. 避免长事务
5. 避免让数据库进行各种大量运算
6. 对于一些对延迟很敏感的业务,直接使用主库读

8、读写分离

读写分离解决的是,数据库的写操作,影响了查询的效率,适用于读远大于写的场景。读写分离的实现基础是主从复制,主数据库利用主从复制将自身数据的改变同步到从数据库集群中,然后主数据库负责处理写操作(当然也可以执行读操作),从数据库负责处理读操作,不能执行写操作。并可以根据压力情况,部署多个从数据库提高读操作的速度,减少主数据库的压力,提高系统总体的性能。

8.1 读写分离提高性能的原因:

(1)增加物理服务器,负荷分摊;
(2)主从只负责各自的写和读,极大程度的缓解X锁和S锁争用;
(3)从库可配置MyISAM引擎,提升查询性能以及节约系统开销;
(4)主从复制另外一大功能是增加冗余,提高可用性,当一台数据库服务器宕机后能通过调整另外一台从库来以最快的速度恢复服务。

8.2 Mysql读写分写的实现方式:

(1)基于程序代码内部实现:在代码中根据select 、insert进行路由分类。优点是性能较好,因为程序在代码中实现,不需要增加额外的硬件开支,缺点是需要开发人员来实现,运维人员无从下手。
(2)基于中间代理层实现:代理一般介于应用服务器和数据库服务器之间,代理数据库服务器接收到应用服务器的请求后根据判断后转发到后端数据库,有以下代表性的代理层。

https://blog.****.net/a745233700/article/details/85413179

9、分库分表

9.1 原因

读写分离解决的是数据库读写操作的压力,但是没有分散数据库的存储压力,利用分库分表可以解决数据库的储存瓶颈,并提升数据库的查询效率。

9.2 拆分⽅案

1、垂直拆分
(1)垂直分表
将一个表按照字段分成多个表,每个表存储其中一部分字段。一般会将常用的字段放到一个表中,将不常用的字段放到另一个表中。

优点:
(1)避免IO竞争减少锁表的概率。因为大的字段效率更低,第一,大字段占用的空间更大,单页内存储的行数变少,会使得IO操作增多;第二数据量大,需要的读取时间长。
(2)可以更好地提升热门数据的查询效率。

(2)垂直分库
按照业务模块的不同,将表拆分到不同的数据库中,适合业务之间的耦合度非常低、业务逻辑清晰的系统。

优点:
降低业务中的耦合,方便对不同的业务进行分级管理
可以提升IO、数据库连接数、解决单机硬件存储资源的瓶颈问题

(2)垂直拆分(分库、分表)的缺点

主键出现冗余,需要管理冗余列
事务的处理变得复杂
仍然存在单表数据量过大的问题

2、⽔平拆分
(1)⽔平分表
在同一个数据库内,把同一个表的数据按照一定规则拆分到多个表中。

优点:
解决了单表数据量过大的问题
避免IO竞争并减少锁表的概率

(2)⽔平分库
把同一个表的数据按照一定规则拆分到不同的数据库中,不同的数据库可以放到不同的服务器上。

优点:
解决了单库大数据量的瓶颈问题
IO冲突减少,锁的竞争减少,某个数据库出现问题不影响其他数据库,提高了系统的稳定性和可用性

(2)水平拆分(分表、分库)的缺点:

分片事务一致性难以解决
跨节点JOIN性能差,逻辑会变得复杂
数据扩展难度大,不易维护

10、常见问题

10.1 为什么推荐使用自增 id 作为主键?

1.普通索引的 B+ 树上存放的是主键索引的值,如果该值较大,会 导致普通索引的存储空间较大
2.使用自增 id 做主键索引新插入的数据只要放在该页的最尾端就可以,直接按照顺序插入 ,不用刻意维护
3.页分裂容易维护,当插入数据的当前页快满时,会发生页分裂的现象,如果主键索引不为自增 id,那么数据就可能从页的中间插入,页的数据会频繁地变动, 导致页面分裂维护成本较高

10.2 WAl 是什么?有什么好处?

WAL 就是 Write-Ahead Logging,其实就是 所有的修改都先被写入到日志中,然后再写磁盘 ,用于保证数据操作的原子性和持久性。
好处:

  1. 读和写可以完全地并发执行 ,不会互相阻塞
  2. 先写入 log 中,磁盘写入从随机写变为顺序写 ,降低了 client 端的延迟。并且,由于顺序写入大概率是在一个磁盘块内,这样产生的 io 次数也大大降低
  3. 写入日志当数据库崩溃的时候 ,可以使用日志来恢复磁盘数据
10.3 什么是回表?

回表就是先通过数据库索引扫描出该索引树中数据所在的行,取到主键 id,再通过主键 id取出主键索引数中的数据,即基于非主键索引的查询需要多扫描一棵索引树。

10.4 什么是索引下推?

在索引遍历过程中,对索引中包含的字段先做判断,直接过滤掉不满⾜条件的记录,减少回表次数。

10.5 什么是覆盖索引?

在 普通索引树中,就可以直接查到待查结果,⽽不需要回表
由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使⽤覆盖索引是⼀个常⽤的性能优化⼿段。

10.6 undolog 是做什么的?

undolog 是 InnoDB 存储引擎的日志,用于保证数据的原子性,保存了事务发生之前的数据版本,可以用于回滚 ,同时可以提供多版本并发控制下的读(MVCC)。主要作用事务回滚、实现多版本控制(MVCC)

10.7 redolog 是做什么的?

redolog 是 InnoDB 存储引擎所特有的一种日志,记录的是数据修改之后的值,不管事务是否提交都会记录下来。先写日志,再写磁盘。

10.8 binlog 是做什么的?

binlog属于 Server 层的日志,以二进制的形式记录,用于数据库的基于时间点的还原 。提交事务记录binlog,定时刷盘。主要用于主从复制和数据恢复。

10.9 relaylog 是做什么的?

relaylog 是中继日志, 在主从同步的时候使用到,它是一个中介临时的日志文件,用于存储从master节点同步过来的binlog日志内容。

10.10 redo log VS. binlog
  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都 可以使⽤。
  2. redo log 记录了具体的数值,对某个页做了什么修改;binlog 记录的是操作内容。
  3. redo log 是循环写的,只有固定大小;binlog 是追加写⼊的,binlog ⽂件写到⼀定⼤⼩后会切换到下⼀个,并不会覆盖以前的⽇志。
10.11 一条 Sql 语句查询一直慢会是什么原因?
  1. 没有用到索引 比如函数导致的索引失效,或者本身就没有加索引
  2. 表数据量太大 考虑分库分表
  3. 优化器选错了索引
10.12 一条 Sql 语句查询偶尔慢会是什么原因?
  1. 数据库在刷新脏页 比如 redolog 写满了 , 内存不够用了,释放内存如果是脏页也需要刷,mysql 正常空闲状态刷脏页
  2. 没有拿到锁
10.13 Sql 调优思路
  1. 表结构优化

拆分字段
字段类型的选择
字段类型大小的限制
合理的增加冗余字段
新建字段一定要有默认值

  1. 索引方面

索引字段的选择
利用好mysql支持的索引下推,覆盖索引等功能
唯一索引和普通索引的选择

  1. 查询语句方面

避免索引失效
合理的书写where条件字段顺序
小表驱动大表
可以使用force index()防止优化器选错索引

  1. 分库分表