Mysql基础知识总结

136 阅读13分钟

字段类型

  • unsigned:是指无符号整数;
  • char和varchar:char是定长字符串,如果设置了长度会在右边自行补充空格;varchar是不定长字符串。
  • decimal和float/Double:decimal是用于金融领域,提供了固定精度和精确算数,float和double就是二进制浮点数。
  • Text和Blob:用于存储长文本数据,Blob用于存储视频的二进制文件。
  • Datetime和TimeTamp:前者是时间,后者是时间戳,后者会考虑时区;
  • null和‘’:null不是为空,而是指值不确定,前者会占内存,后者不会占用;
  • tinyin(1):没有专门的boolean类型,这个是,1或者0.

Mysql的基础构架

mysql的基础构架?

连接器、解析器、优化器、执行器和存储引擎。

mysql是怎么执行一条select语句过程发生了什么?

  • 连接器先连接客户端,身份验证,权限验证;
  • 解析器进行语法解析、语义解析;
  • 优化器成本,并且选择成本最小的方案;
  • 执行器;执行器执行计划,并且通过存储引擎获取数据。

mysql是怎么执行一条update语句过程发生了什么?

  • 连接器先连接客户端,验证权限;
  • 解析器进行语法解析、语义解析;
  • 优化器,选择成本最小的方案;
  • 执行器:
    • 先查找到需要修改的数据行,将数据进行修改;
    • 然后将修改写入到redo log中,记录为prepare状态;
    • 再将其写入到binlog里面,并将其写入磁盘,
    • 最后在redo log里面改commit状态。

完成了updata语句的。

Mysql的存储引擎

Mysql又是什么存储引擎?

Innodb、MyISAM和Memery

说说Innodb、MyISAM的区别?

在mysql5.5.5之前默认使用的MyISAM,在Innodb之后是Innodb。

二者的区别:

  • 锁:MyISAM只支持表级锁;Innodb支持行级锁,也支持表级锁;
  • 多版本并发控制MVCC:MyISAM不支持,Innodb支持;
  • 事务:MyISAM不支持事务,Innodb支持事务;
  • 外键的支持:IMyISAM不支持外键,Innodb支持外键;
  • 异常恢复:MyISAM不支持异常崩溃上的安全恢复,Innodb支持;(Innodb的日志redolog和undolog)
  • 索引:虽然二者都是B+树但是具体的实现方式不同,Innodb是聚簇索引,MyISAM是非聚簇索引。

(什么是聚簇索引,什么是非聚簇索引?

聚簇索引和非聚簇索引最主要的区别是数据和索引是否分开存储。

聚簇索引:将数据和索引放到一起存储,索引结构的叶子节点保留了数据行。

非聚簇索引:将数据进和索引分开存储,索引叶子节点存储的是指向数据行的地址。

在InnoDB存储引擎中,默认的索引为B+树索引,利用主键创建的索引为主索引,也是聚簇索引,在主索引之上创建的索引为辅助索引,也是非聚簇索引。为什么说辅助索引是在主索引之上创建的呢,因为辅助索引中的叶子节点存储的是主键。

在MyISAM存储引擎中,默认的索引也是B+树索引,但主索引和辅助索引都是非聚簇索引,也就是说索引结构的叶子节点存储的都是一个指向数据行的地址。并且使用辅助索引检索无需访问主键的索引。
原文链接:www.mianshi.online/mysql-clust…

日志文件

常见的日志文件:

  • error log:错误日志,记录Mysql启动,运行,关闭的日志;
  • general log:一般查询日志,记录所有对Mysql的请求,无论请求是否正确;
  • bin log:二进制日志,记录对数据库表结构或表数据的修改,多用于对数据的备份和复制;

Innodb(独有):

  • redo log:重做日志,记录了对于Innodb存储引擎的事务日志,实现了事务的持久性;
  • undo log:回滚日志,作用于对事务进行回滚,实现了事务的原子性;

bin log和redo log有什么区别?

  • bin log多种存储引擎都存在,redo log只存在于Mysql;
  • 使用场景:bin log多用于备份和复制,redo log则是用于故障恢复;
  • 写入方式不同:bin log是追加写入,而redo log是循环写;
  • bin log记录的是关于一个事务的具体操作,是逻辑日志;而redo log记录的是对于某页具体的操作,也就是物理日志,比如对 XXX 表空间中的 YYY 数据页 ZZZ 偏移量的地方做了AAA 更新;。

bin log什么时候刷盘?

为了持久化考虑,大概有三种情形:

  • 提交事务后刷盘;
  • 在binlog有一个bin log buffer区,如果超过一半左右也会刷盘;
  • 后台有线程,每秒刷一次盘。

索引

索引有哪些?

类型来说:唯一索引,组合索引,普通索引

数据结构来分有:hash索引,B树,B+数

物理存储:

  • 聚簇索引:索引和数据放在一起
  • 非聚簇索引:索引和数据不放在一起

为什么使用索引?索引怎么加快查询?

原因:加快查询效率

当建立索引会根据BTREE算法生成索引文件,查找数据就先查索引,再根据索引找到具体试数据,就和看书翻目录一样。

什么时候创建索引?

  • 在数据量大的表;
  • 和其他表有联系的字段,比如外键;
  • 需要排序的列:索引能够加快查询效率;
  • 有唯一性的约束的列。

什么时候不适合创建索引?

  • 小表,数据少:索引可能还没有直接遍历快;
  • 数据离散差:比如性别,只有男女,建立索引就不是很好;
  • 需要频繁更改的表:频繁的更改索引,提高资源开销。

什么情况下索引会失效?(9:4个关键字的问题,三个在对列上进行操作的问题,编码格式问题)

  • 关键字or:某一条件没有索引,可能会导致,直接放弃使用索引全表查询;
  • like:是模糊查询,%的使用,可能会导致失效;
  • != <>:
  • is null 和 is not null:不适等值判断
  • 联合索引,查询的一个列不是联合索引的第一列:因为根据最左匹配原则;
  • 在索引列上使用内置函数;
  • 对查询字段进行加减乘除处理;
  • 对于字符串没有用双引号,被隐式转换(解决办法:通过concat进行显式转换)
  • 左连接或者有连接,连接查询的关键字编码格式不一样。

索引的数据结构?为什么使用B+锁?为什么树不深?

Innodb的底层使用的式B+树,叶子节点之间被双向链表连接,叶子结点只存放索引,不存放数据,数据只存放在非叶子节点,Innodb的为6b,一页为16kb。

考虑到三个方面:

  • 从增删来说,B+数有很多冗余节点,对数据进行增删,很方便并且不易导致数据的变形;
  • 从查询来说:扫库或者扫表,查询效率很稳定;
  • 数据结构,让B+树不深,但是能存储千万级数据,减少了磁盘的IO数据。

回表查询?覆盖索引?索引下推优化?

回表查询就是,根据辅助索引查找主键索引的键值之后,还得再去根据这个键值回去查找数据,这就是回表查询。

在辅助索引里面,不管是单列索引还是联合索引,如果 select 的数据列只用辅助索引中就能够取得,不用去查主键索引,这时候使用的索引就叫做覆盖索引,避免了回表。通过覆盖索引可以解决,就是把主键值作为查询条件。

索引下推优化一定程度也可以减少回表,具体来说,就是把部分查询条件推至存储引擎。

(索引下推优化的核心思想是在执行索引查找的时候,将一部分查询条件下推至存储引擎层,由存储引擎直接进行判断。如果存储引擎能够判断某个条件并在索引上进行过滤,就可以避免将不符合条件的数据传递到 MySQL 服务器层,减少了回表的次数。)

最左前缀原则?/最左匹配原则?

最左匹配原则:在 InnoDB 的联合索引中,查询的时候只有匹配了前一个/左边的值之后,才能匹配下一个。

根据最左匹配原则,我们创建了一个组合索引,如 (a1,a2,a3),相当于创建了(a1)、(a1,a2)和 (a1,a2,a3) 三个索引。

事务

什么是事务?

事务指的是一组操作,要么都执行,要么都不执行。

事务的四大特性?

A:原子性,事务要么全部完成,要么全部不完成,没有中间状态;undo log,会在日志中记录旧值,如果提交成功,在某个时间会自动删除,如果没有提交,会回滚撤销所有更改。

C:一致性:事务开始之前和结束之后,数据不会被破坏。

D:持久性:事务一旦提交修改,将持久的保存在数据库中。通过redo log实现,具体来说就是,通过先不修改数据,而是“先写日志”,即使数据库崩溃,通过redo log恢复,如果redo log写满了,就有可能直接去改数据库文件。

I:隔离性:事务和事务之间存在隔离。MVCC

事务的隔离级别:

读未提交:事务还没有提交修改,就被其他事务读取该修改。脏读

读已提交:事务提交之后才可以被读到。不可重复读。

可重复读:在同一事务多次读取某个数据,数据是一样的。

串行化:后访问的事务,必须等前一个事务执行完成,才会执行。(并发性差)

隔离级别脏读不可重复读幻读
读未提交
读已提交
可重复读
串行化

什么是幻读,脏读,不可重复读?

幻读:事务A查询到某个结果集,事务B提交对结果集进行了增删,事务A再次查询的结果集就不一致了

脏读:某一个事务读数据的时候,读取到的是另一个事务修改的数据,但是另一事务没有提交。

不可重复读:同一个事务在读数据的时候,前面读到的数据和后面读到的数据不一致。

如何保证事务开启/Mysql的事务传播行为?

MVCC?

MVCC也是多版本并发控制,用来保持原子性。

每一个undo log都有一个回滚指针指向上一个undo log这样就行一个版本链,但是具体要差哪一个版本就要靠read view,在read view中有四个关键的值:创建该事务的id,当前所有活跃的事务id,最小活跃事务的id,下一个要分配事务的id。

如果小于最小活跃的事务id,说明已经执行完了,数据可见;

如果大于下一个要分配的事务id,说明还没有开始执行,数据不可见;

如果大于最小的活跃的事务id,但是大于最大活跃的事务id:

  • 查询是否在当前所有的事务的id中,如果在是说明,还没执行,数据不可见;
  • 如果不在,说明执行完了,数据可见。

读取数据的方式:快照读和当前读?

快照读:读的数据不是最新的数据,而是快照数据,适用于对一致性要求高的场景。为了解决幻读,通过MVCC

当前读:读取的时当前最新已经提交的数据,适用于对一致性要求不高的场景。为了解决幻读通过临值锁(记录锁+间隙锁)实现。

Innodb中有几种锁?

行级锁:锁住某一行记录,锁粒度更小,针对索引字段加的锁,锁开销大;

表级锁:锁住某张表,实现简单资源消耗小,不会死锁。

MyISM只有表级锁,Innodb都有。

说一说行锁的实现?

记录锁:锁住某一行记录;

间隙锁:锁住某记录的中间的值,不包括记录本身值;

临值锁:记录锁+间隙锁,锁住记录和其间隙;

Inndb默认使用的时记录锁和间隙锁,但是如果对象是唯一索引,那么会降级为记录锁。

共享锁和排他锁?

共享锁:又称读锁,多个事务都可以获得,

排他锁:又称写锁,由某个事务独占,锁独占。

排他锁和任何锁都不兼容,共享锁只和共享锁兼容。

意向锁是什么知道吗?

意向锁是表级锁,为了判断该表中是否有其他锁,所以通过意向锁,在加锁之前需要先获取到意向锁。

意向锁之间不互相排斥,意向锁和表级别的锁,只有共享锁和意向共享锁兼容,其他的都互斥。

自增锁

这是对于设置为自增的键,增加的锁。

分布式

读写分离

  • 数据库搭建了主从集群,或者一主多群;
  • 数据库中都有所有的业务数据;
  • 主数据库负责接收写请求,从数据库接收读请求。

主从复制

主从复制的步骤:

  • 主机的修改记录进入bin log;
  • 从机通过dump线程将bin log推送到从数据库;
  • 从数据库连接到master的时候,创建IO线程接收bin log,复制到中继(relay log)日志;
  • 从数据库通过relay log执行;
  • 将修改记录进入到从数据库的bin log.

慢SQL优化

慢 SQL 优化的步骤可以精简为以下几个方面:

  • 分析语句的执行计划,查看SQL语句的索引是否命中 优化数据库的结构,
  • 将字段很多的表分解成多个表,或者考虑建立中间表。
  • 优化LIMIT分页。

使用索引: 确保查询中涉及的字段上有适当的索引,以加速数据检索。

避免全表扫描: 尽量避免在大表上执行全表扫描,可以通过使用合适的索引或者优化查询语句来实现。

减少返回的数据量: 只选择需要的列,避免一次性返回过多的数据。

使用合适的数据类型: 选择合适的数据类型,避免不必要的数据类型转换。

优化查询语句: 确保 SQL 查询语句的写法是高效的,避免不必要的子查询,使用连接操作等。

分析执行计划: 使用数据库的执行计划工具,分析查询语句的执行计划,找出可能存在的性能瓶颈。(slow_query_log)

缓存重复查询结果: 对于一些查询结果比较稳定的数据,可以考虑使用缓存,避免重复查询。

分析数据库结构: 确保数据库表的设计是合理的,避免冗余字段、重复数据等问题。

定期清理无用数据: 删除不再需要的数据,定期清理日志等,保持数据库的轻量级。