面试准备--MySql

863 阅读6分钟

日志

redo log

redo log是InnoDB特有的物理日志,有固定空间,循环写入,记录“某个数据页上做了什么修改”。当数据库发生异常重启时,redo log可以确保数据不会丢失。

binlog

binlog,归档日志,记录sql语句的原始逻辑。由MySql server层实现,所有引擎都可以使用。binlog是追加写入的。当存放binlog的日志文件到指定大小后,会写入新的文件,不会覆盖之前的日志文件。

索引

InnoDB引擎索引的数据结构是B+树。根据叶子节点存放的内容,索引的类型分为主键索引和非主键索引。

  • 主键索引:叶子节点是整行数据,也叫聚簇索引。
  • 非主键索引:叶子节点是主键,也叫二级索引。通过非主键索引查询时,先找到要找的数据的主键,再通过主键索引查询整行数据,这个过程叫做回表。

覆盖索引

当使用非主键索引查询时,如果需要查询的字段已经在索引树上,则不需要回表即可查询到需要的字段。覆盖索引是常见的优化sql的手段。

重建索引

alter table T engine=InnoDB;

最左前缀原则

以一定顺序引用多个列,叫联合索引。比如ALTER TABLE table_name ADD INDEX index_name (a, b, c);当查询条件中,有字段a时,就会命中这个索引,当只有字段b或c时,不会命中索引。
这个最左前缀可以是联合索引的最左 N 个字段,也可以是字符串索引的最左 M 个字符。

索引选择

当执行explain语句时,会看到预计的扫描行数,这个扫描行数是MySql优化器选择索引的一个参考条件。
MySql在执行sql语句之前,并不能精确的知道满足条件的记录有多少条,是通过索引的区分度来估计统计条数的(可以通过show index from table来查看)。MySql在计算索引的区分度时,会默认选择N个数据页,计算这N个数据页上的不同值,取平均数,乘以索引的页面数,就能得到这个索引的基数。
当数据变更的行数超过1/M时,会自动触发,重新进行索引统计,也可以通过analyze table t语句来手动触发。 在 MySQL 中,有两种存储索引统计的方式,可以通过设置参数 innodb_stats_persistent 的值来选择:

  • 设置为 on 的时候,表示统计信息会持久化存储。这时,默认的 N 是 20,M 是 10。
  • 设置为 off 的时候,表示统计信息只存储在内存中。这时,默认的 N 是 8,M 是 16。

当发现MySql没有选择正确的索引时,可以通过使用force index来指定我们认为正确的索引。select * from t force index (a) where ...。
但是使用force index会面临当索引名称发生改变时,需要改sql语句,不利于维护。这时候我们可以通过改变sql语句,来诱导MySql使用我们希望的索引,或者建立一个更合适的索引,删掉错误的索引来达到目的。

索引失效

  • like 语句以%开头
  • 在使用多列索引时,没有遵守最左匹配原则。即当查询条件中,有第一列字段时,索引才会生效
  • 在使用or语句时,当前后条件都有索引,才会生效
  • 如果列类型是varchar,需要用引号,否则索引不会生效
  • 对查询的列有运算或使用函数,索引不会生效
  • 当全表扫描比使用索引快,索引不生效

事务

事务的特性:原子性、一致性、隔离性、持久性
多个事务同时执行时,可能会出现的问题:

  • 幻读:A事务处理过程中,B事务新增了满足A事务查询的数据,导致A事务前后查询的结果不一致(insert 需要锁表解决)
  • 脏读:一个事务在处理过程中,读取了另一个事务没有提交的数据
  • 不可重复读:A事务处理过程中,B事务对数据做了修改或删除,导致A事务前后查询的结果不一致(update和delete 需要锁行解决)

隔离级别

  • 读未提交:一个事务没有提交,做的变更就能被别的事务看到
  • 读提交:一个事务提交之后,做的变更才能被其他事务看到
  • 可重复读:一个事务在执行过程中看到的数据,和这个事务在启动时的数据是一致的。未提交的变更,其他事务也看不到
  • 串行化:对于同一条记录,写会加“写锁”,读加“读锁”。当读写锁出现冲突时,后访问的事务必须等待之前的事务执行完成方可执行

事务隔离的实现

每条记录在更新的时候都会同时记录一条回滚操作。同一条记录在系统中可以存在多个版本,这就是数据库的多版本并发控制(MVCC)。当系统判断没有事务需要用到回滚日志的时候,就会删除回滚日志。

explain

可以通过explain语句来了解sql是怎么执行的

id

一般来说一个select一个唯一id,如果是子查询,就有两个select,id是不一样的

select_type

  • simple:不包括union和子查询的查询都算simple类型。
  • primary:包括union,union all,其中最左边的查询即为primary。
  • union:包括union,union all,除了最左边的查询,其他的查询类型都为union。

table

显示这一行是关于哪张表的

type

  • ref:普通二级索引与常量等值匹配
  • ref_or_null:普通二级索引与常量等值匹配,该索引可能为null
  • const:唯一二级索引或主键索引与常量等值匹配
  • range:范围区间查询
  • all:全表扫描

possible_keys、

对某张表进行单表查询时,可能用到的索引

keys

优化器经过计算成本,最终选择的索引

rows

  • 如果是全表扫描,则表示需要扫描的行数
  • 如果使用,则表示预计扫描的行数

filtered

  • 如果是全表扫描,则表示满足搜索条件的记录的占比
  • 如果是索引,则表示除去索引对应的搜索,其他搜索条件的百分比