Mysql

1/5/2023 数据库

# 1. 什么是索引

索引是为了加速对表中数据行的检索而创建的一种分散存储的数据结构

# 2. 为什么要用索引

1. 索引能极大的减少存储引擎需要扫描的数据量
2. 索引可以把随机IO变成顺序IO
3. 索引可以帮助我们在进行分组、排序等操作时,避免使用临时表

# 3. 为什么不用平衡二叉树

1. 它太深了。数据处的(高)深度决定着他的IO操作次数,IO操作耗时大
2. 它太小了。每一个磁盘块(节点/页)保存的数据量太小了
3. 没有很好的利用操作磁盘IO的数据交换特性,     
4. 没有利用好磁盘IO的预读能力(空间局部性原理),从而带来频繁的IO操作
(平衡二叉树)
(B+Tree)

# 4. B+Tree与B-Tree的区别

1. B+节点关键字搜索采用闭合区间
2. B+非叶节点不保存数据相关信息,只保存关键字和子节点的引用
3. B+关键字对应的数据保存在叶子节点中
4. B+叶子节点是顺序排列的,并且相邻节点具有顺序引用的关系

# 5. 为什么选用B+Tree

1. B+树是B树的变种(PLUS版)多路绝对平衡查找树,他拥有B-树的优势
2. B+树扫库、表能力更强
3. B+树的磁盘读写能力更强
4. B+树的排序能力更强
5. B+树的查询效率更加稳定(仁者见仁、智者见智)

# 6. Innodb & Myisam 索引实现方式

(Innodb & Myisam)

# 7. 如何选择索引列

1. 列的离散性越高越好

# 8. 什么是覆盖索引

如果查询列可通过索引节点中的关键字直接返回,则该索引称之为覆盖索引。

# 9. Myisam 存储引擎与Innodb 存储引擎区别

Myisam:
1. select count(*) from table  无需进行数据的扫描 
2. 数据(MYD)和索引(MYI)分开存储 
3. 表级锁 
4. 不支持事务

Innodb:
1. 支持事务ACID
2. 行级锁
3. 聚集索引
4. 支持外键关系保证数据完整性

# 10. 查询执行的过程

1. mysql 客户端与服务端通信(半双工)
2. 查询缓存(默认关闭)
3. 解析器解析成解析树
4. 优化器查询优化处理(优化count min max覆盖索引扫描 limit in二分查找)
5. 查询执行引擎
6. 返回客户端

# 11. 执行计划 select_type

1. SIMPLE:简单的select查询,查询中不包含子查询或者union 
2. PRIMARY:查询中包含子部分,最外层查询则被标记为primary 
3. SUBQUERY/MATERIALIZED:SUBQUERY表示在select 或 where列表中包含了子查询MATERIALIZED表示where 后面in条件的子查询
5. UNION:若第二个select出现在union之后,则被标记为union;
6. UNION RESULT:从union表获取结果的select

# 12. 执行计划 type

system > const > eq_ref > ref > range > index > ALL
1. system:表只有一行记录(等于系统表),const类型的特例,基本不会出现,可以忽略不计
2. const:表示通过索引一次就找到了,const用于比较primary key 或者 unique索引
3. eq_ref:唯一索引扫描,对于每个索引,表中只有一条记录与之匹配。常见于主键或唯一索引
4. ref:非唯一性索引扫描,返回匹配某个单独值的所有行,本质是也是一种索引访问
5. range:只检索给定范围的行,使用一个索引来选择行 (like、> 、<)
6. index:Full Index Scan,索引全表扫描,把索引从头到尾扫一遍
7. ALL:Full Table Scan,遍历全表以找到匹配的行

# 13. 执行计划-其他参数

1. possible_keys 查询过程中有可能用到的索引
2. key 实际使用的索引,如果为NULL,则没有使用索引 
3. rows 根据表统计信息或者索引选用情况,大致估算出找到所需的记录所需要读取的行数
4. filtered 它指返回结果的行占需要读到的行(rows列的值)的百分比 表示返回结果的行数占需读取行数的百分比,filtered的值越大越好。
5. Using filesort : mysql对数据使用一个外部的文件内容进行了排序,而不是按照表内的索引进行排序读取
6. Using temporary: 使用临时表保存中间结果,也就是说mysql在对查询结果排序时使用了临时表,常见于order by 或 group by 
7. Using index: 表示相应的select操作中使用了覆盖索引(Covering Index),避免了访问表的数据行,效率高 
8. Using where : 使用了where过滤条件
9. select tables optimized away: 基于索引优化MIN/MAX操作或者MyISAM存储引擎优化COUNT(*)操作,不必等到执行阶段在进行计算,查询执行 计划生成的阶段即可完成优化

# 14. 什么是事务?

事务:数据库操作的最小工作单元,是作为单个逻辑工作单元执行的一系列操作; 事务是一组不可再分割的操作集合(工作逻辑单元);

# 15. 事务的ACID

1. 原子性(Atomicity)最小的工作单元,整个工作单元要么一起提交成功,要么全部失败回滚
2. 一致性(Consistency) 事务中操作的数据及状态改变是一致的,即写入资料的结果必须完全符合预设的规则,不会因为出现系统意外等原因导致状态的不一致
3. 隔离性(Isolation) 一个事务所操作的数据在提交之前,对其他事务的可见性设定(一般设定为不可见)
4. 持久性(Durability) 事务所做的修改就会永久保存,不会因为系统意外导致数据的丢失

# 16. 事务并发的问题

1. 脏读:未提交读
2. 不可重复读
3. 幻读(范围读,读两次条数不一样)

# 17. 事务隔离级别

1. RU:未提交读(未解决并发问题)事务未提交对其他事务也是可见的
2. RC:提交读 (解决脏读)一个事务开始之后,只能看到自己提交的事务所做的修改,不可重复读
3. RR:可重复读(解决不可重复读问题)在同一个事务中多次读取同样的数据结果是一样的,这种隔离级别未定义解决幻读的问题
4. Serializable:串行化(解决所有问题)最高的隔离级别,通过强制事务的串行执行

# 18. 锁类型

1. 共享锁(行锁):Shared Locks 
2. 排它锁(行锁):Exclusive Locks 
3. 意向共享锁(表锁):Intention Shared  Locks 
4. 意向排它锁(表锁):Intention Exclusive Locks 
5. 自增锁:AUTO-INC Locks 
行锁的算法:
6、记录锁 Record Locks 
7、间隙锁 Gap Locks 
8、临键锁 Next-key Locks

# 19. 共享锁:

又称为读锁,简称S锁,顾名思义,共享锁就是多个事务对于同一数据可以共享一把锁,
都能访问到数据,但是只能读不能修改;
加锁释锁方式: select * from users WHERE id=1 LOCK IN SHARE MODE; commit/rollback

# 20. 排他锁:

又称为写锁,简称X锁,排他锁不能与其他锁并存,
如一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁、排他锁),
只有该获取了排他锁的事务是可以对数据行进行读取和修改,(其他事务要读取数据可来自于快照)
加锁释锁方式: delete / update / insert 
默认加上X锁 SELECT * FROM table_name WHERE ... FOR UPDATE commit/rollback

# 21. InnoDB行锁是怎么实现的

InnoDB的行锁是通过给索引上的索引项加锁来实现的。
只有通过索引条件进行数据检索,InnoDB才使用行级锁,否则,InnoDB 将使用表锁(锁住索引的所有记录)

# 22. 意向共享锁(IS)

表示事务准备给数据行加入共享锁,即一个数据行加共享锁前必须先取得该表的IS锁, 意向共享锁之间是可以相互兼容的

# 23. 意向排它锁(IX)

表示事务准备给数据行加入排他锁,即一个数据行加排他锁前必须先取得该表的IX锁, 意向排它锁之间是可以相互兼容的
意向锁(IS、IX)是InnoDB数据操作之前自动加的,不需要用户干预
意义:
当事务想去进行锁表时,可以先判断意向锁是否存在,存在时则可快速返回该表不能启用表锁,不需要去深层扫描数据判断。

# 24. 自增锁

针对自增列自增长的一个特殊的表级别锁

# 25. Next-key locks: 临键锁 (解决幻读)

锁住记录+区间(左开右闭) 当sql执行按照索引进行数据的检索时,
查询条件为范围查找(between and、<、>等)
并有数据命中则此时SQL语句加上的锁为Next-key locks,
锁住索引的记录+区间(左开右闭)

# 26. Gap locks:间隙锁

锁住数据不存在的区间(左开右开) 
当sql执行按照索引进行数据的检索时,查询条件的数据不存在,
这时SQL语句加上的锁即为 Gap locks,锁住索引不存在的区间(左开右开)

# 27. Record locks:记录锁

锁住具体的索引项 当sql执行按照唯一性(Primary key、Unique key)索引进行数据的检索时,
查询条件等值匹 配且查询的数据是存在,这时SQL语句加上的锁即为记录锁Record locks,锁住具体的索引项

# 28. 锁怎么解决事务并发问题

脏读:通过添加X锁
不可重复读:加上S锁
幻读:加上临键锁

# 29. 死锁

多个并发事务(2个或者以上);
每个事务都持有锁(或者是已经在等待锁);
每个事务都需要再继续持有锁;
事务之间产生加锁的循环等待,形成死锁。

# 30. 如何避免死锁

类似的业务逻辑以固定的顺序访问表和行。
为表添加合理的索引。可以看到如果不走索引将会为表的每一行记录添加上锁(或者说是表锁)
在同一个事务中,尽可能做到一次锁定所需要的所有资源,减少死锁概率。

# 31. MVCC

Multiversion concurrency control  (多版本并发控制)
并发访问(读或写)数据库时,对正在事务内处理的数据做多版本的管理。以达到用来避免写操作的堵塞,从而引发读操作的并发问题。
MVCC-新增: 数据版本号存储当前的事务ID,删除版本号为null
MVCC-编辑: 将删除版本号设置成当前的事务ID
MVCC-修改: 将原来数据的版本号删除版本号设置成当前事务的ID,将原有数据复制一份,数据版本号设备成当前事务ID,删除版本号为null
MVCC-查询: 数据版本号小于或等于当前事务ID,删除版本号为null,或大于当前事务ID。

# 32. Undo log

1. undo log指事务开始之前,在操作任何数据之前,首先将需操作的数据备份到一个地方 (Undo Log)
2. UndoLog是为了实现事务的原子性而出现的产物
3. Undo Log实现事务原子性: 事务处理过程中如果出现了错误或者用户执行了ROLLBACK语句,
    Mysql可以利用Undo Log中的备份 将数据恢复到事务开始之前的状态
4. UndoLog在Mysql innodb存储引擎中用来实现多版本并发控制
5. Undo log实现多版本并发控制: 事务未提交之前,Undo保存了未提交之前的版本数据,
    Undo 中的数据可作为数据旧版本快照供 其他并发事务进行快照读。

# 33. 快照读:

SQL读取的数据是快照版本,也就是历史版本,普通的SELECT就是快照读
innodb快照读,数据的读取将由 cache(原本数据) + undo(事务修改过的数据) 两部分组成

# 34. 当前读:

SQL读取的数据是最新版本。通过锁机制来保证读取的数据无法通过其他事务进行修改
UPDATE、DELETE、INSERT、SELECT …  LOCK IN SHARE MODE、SELECT … FOR UPDATE都是当前读。

# 35. Redo Log

Redo,顾名思义就是重做。以恢复操作为目的,重现操作; Redo log指事务中操作的任何数据,将最新的数据备份到一个地方 (Redo Log)
RedoLog的持久: 不是随着事务的提交才写入的,而是在事务的执行过程中,便开始写入redo 中。具体的落盘策略可以进行配置
RedoLog是为了实现事务的持久性而出现的产物
RedoLog实现事务持久性: 防止在发生故障的时间点,尚有脏页未写入磁盘,在重启mysql服务的时候,根据redo log进行重做,从而达到事务的未入磁盘数据进行持久化这一特性。
指定Redo log 记录在{datadir}/ib_logfile1&ib_logfile2   
可通过innodb_log_group_home_dir 配置指定 目录存储
一旦事务成功提交且数据持久化落盘之后,此时Redo log中的对应事务数据记录就失去了意义,所以Redo log的写入是日志文件循环写入的。
指定Redo log日志文件组中的数量 innodb_log_files_in_group 默认为2 
指定Redo log每一个日志文件最大存储量innodb_log_file_size  默认48M 
指定Redo log在cache/buffer中的buffer池大小innodb_log_buffer_size 默认16M
Redo buffer 持久化Redo log的策略, 
Innodb_flush_log_at_trx_commit: 
取值 0  每秒提交 Redo buffer  -->  Redo log  OS cache -->flush cache to disk[可能丢失一秒内 的事务数据] 
取值 1  默认值,每次事务提交执行Redo buffer  -->  Redo log  OS cache -->flush cache to disk [最安全,性能最差的方式] 
取值 2  每次事务提交执行Redo buffer  -->  Redo log  OS cache  再每一秒执行 ->flush cache to disk操作

# 36. 配置优化

1、mysql --help  寻找配置文件的位置和加载顺序
2、最大连接数: max_connections  (与下面两项有关)
系统句柄数配置 /etc/security/limits.conf ulimit -a
mysql句柄数配置 /usr/lib/systemd/system/mysqld.service
3、内存参数
    每一个connection内存参数配置:       
    sort_buffer_size:
    connection排序缓冲区大小 建议256K(默认值)-> 2M之内 当查询语句中有需要文件排序功能时,马上为connection分配配置的内 存大小
    join_buffer_size:   
    connection关联查询缓冲区大小 建议256K(默认值)-> 1M之内 当查询语句中有关联查询时,马上分配配置大小的内存用这个关联查询,
    所以有可能在一个查询语句中会分配很多个关联查询缓冲区
    另外:
    Innodb_buffer_pool_size:(很重要)
    innodb buffer/cache的大小(默认128M)
    里面有: Innodb_buffer_pool 数据缓存 索引缓存 缓冲数据 内部结构
    大的缓冲池可以减小多次磁盘I/O访问相同的表数据以提高性能
    https://www.cnblogs.com/wyy123/p/6092976.html 常见配置
更新时间: 2/16/2023, 5:28:01 PM