MySql常见问题

Posted 若甘年后

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySql常见问题相关的知识,希望对你有一定的参考价值。

mysql

1. 事务的四大特性 ACID

  • 原子性 Atomicity

    我们对数据库的一系列操作要么都成功 要么都失败,如果转账场景,一个账户增加 另一个失败,要么都成功或者都失败

  • 一致性 Consistent

    一种是指数据库的完整性月数没有被破坏,比如主键唯一,事务的合法等,另一种是业务的一致性,比如转账场景,A账户余额减少1000,B账户余额增加500,这时候虽然两个操作都成功了,符合了原子性协议,但没有符合一致性

  • 隔离性 Isolation

    数据库中有很多事务同时去访问同一个表或者同一行数据,必然会产生一些并发的影响,这时候就要定义不同的事务让他们之间互不干扰,也是通过这种方式保证数据的一致性

  • 持久性 Durable

    对数据库的任意操作,只要成功了就应该是持久的

数据库的持久性是如何实现的?

通过redo log 和 double write双写缓冲来实现的,我们操作数据的时候,会先写道内存的buffer pool中,同时记录redo log,如果在刷盘之前出现异常,再重启后就可以读取redo log的内容,写入磁盘,保证数据的持久性,当然恢复成功的前提是数据页本身没有被破坏,是完整的 这个是通过双写缓冲来保证的

2. 性能优化

  • 通过开启slow query log 可以把慢查询日志记录下来,并用mysqlDumpSlow分析并导出对应需要的格式

    mysqlDumpSlow -s t -t 20 -g 'select' /usr/local/mysql/data/slow-query.log

  • 通过开启select @@profile 开关 可以查看sql执行所用时间 cpu占用信息等情况,

    select * from information_schema.profiling 表中存储了所有信息

  • 通过show processlist 或者select * from information_schema.processlist 查看所有正在执行的sql线程,看看是否有死锁线程或者等待队列已满等情况

3. EXPLAIN

  • id 笛卡尔积,2 * 3 * 4 = 6 * 4 会优于 3 * 4 * 2 = 12 * 2 因为中间产生的笛卡尔积临时表空间更少

    如果id大小不一样 查询顺序是从大到小进行,如果id大小是一样的,查询顺序是自上而下

  • select_type

    • PRIMARY
    • SUBQUERY
    • DERIVED
    • UNNION ALL
  • table

  • type

    • System 系统只有一行数据
    • const 只查询到一行数据
    • eq_ref 唯一性索引 是对于多表join查询,并且对于前表的每一条结果刚好能匹配到后表的每一条结果
    • ref 非唯一性索引,
    • range 范围查找
    • index full index scan 查询的字段是在索引上的字段
    • all
    • null
  • possible_keys 可能使用到的索引

  • key 实际使用到的索引,如果查询的字段存在于某个索引上,虽然这个索引不符合最左匹配原则,但实际还是会用到索引,此时 possible_keys为null key不为null,

  • rows 扫描到的大概行数

  • filtered 过滤的百分比 越接近100越好

  • extra 附加条件

    • using where 如果存储引擎层返回的数据不是我们最终需要的数据,需要经过server端过滤的时候

      需要索引查询到的数据回表查询,

    • using index 只是用了索引数据,不需要回表去查询数据

    • using index condition 索引下推 查询的条件语句经过索引进一步过滤之后 再返回给server端

    • using filesort 没有使用到对应的索引排序, 用了额外的排序规则

    • using temporary 临时表

4. 一个SQL语句的执行过程

连接--》分析器(词法分析器(把一个sql语句拆分成单个的单词去校验)和语法分析器(按照语法树去分析))--》预处理器--》优化器(query optimizer,会生成所有可能的执行计划,然后基于开销时间获取一个最佳的执行计划) --》执行计划(可以通过explain查看)-》执行引擎

5. mysql 存储文件

  • innodb:
    • .frm文件 表结构文件
    • ibd文件索引文件
  • myisam
    • frm文件 表结构文件
    • myi 索引文件
    • myd 数据文件

6. 存储引擎

  • MYISAM

    • 支持表级别的锁,不支持事务 ,所以插入和更显会锁表

    • 拥有较高的插入和查询速度,适合读多写少的情况

    • 存储了表的count行数,所以count速度更快

      怎么快速向数据库插入100万条数据了,可以先用MYISAM引擎插入数据,然后在修改为INNODB

  • INNODB

    • 支持事务,支持外键,
    • 支持航级别的锁和表级别的锁
    • 支持读写并发,写不阻塞读(MVCC)
    • 特殊的索引存放 可以减少IO

7. INNODB的内存结构和磁盘结构

1. 内存结构(Buffer Pool) 默认128M 可以缓存索引页和数据页

  • Buffer Pool 内存的缓冲池数据写满了怎么办?Innodb使用LRU算法,有一个Buffer Pool List分成Old (3/8)和young(5/8)代,如果查询的数据在缓冲池中已存在,则提升到连表头,如果不存在则放到中间,后面的数据进行末尾淘汰

  • Change Buffer 写缓冲,如果要写入的数据不是唯一索引,也就是说不存在数据重复的情况下,就不需要先从磁盘加载判断唯一性,直接先在缓冲池中更改,从而提升增删改的执行速度,5.5之前的版本叫Insert Buffer 现在可以支持更新和删除,所以更改为Change Buffer

    然后把change Buffer的数据merge,在访问这个数据页的时候merge,通过后台线程、或者数据库发生 shutdown的时候,以及 redo log 写满时触发

    如果数据库的大部分索引都是非唯一索引,并且业务是写多读少,不会在写后立刻读取数据,就可以调大change buffer的值,默认占用 Buffer Pool的25%空间

  • Adaptive Hash index

  • (redo)log buffer 为防止Change Buffer里的数据未同步到磁盘发生宕机,innodb 把所有的写操作都记录在 redo log 中,redo log在表空间中 默认有2个文件,每个文件默认48M,默认都是先写日志 在写磁盘,因为写入磁盘是随机IO,写入日志文件是顺序IO,所以速度更快。默认是每次事务提交的时候 都会把log buffer 写入到磁盘。

    redo log的文件大小是固定的,默认16M,里边有两个指针,一个写指针,一个check指针,如果两个指针重叠,说明文件满了,这个时候需要同步数据到磁盘中

2. 磁盘结构

  • 系统表空间 system tablespace
  • 独占表空间
    • segment 段 数据段 索引段
    • extent 区(簇) 大小是1M 包括64个页
    • page 页 每个页大小是16K
  • 通用表空间

8. 日志文件

  1. redo log 记录修改后的数据,用来更新数据日志 是在存储引擎层完成的
  2. undo log 记录之前的数据,用来恢复数据
  3. bin log 记录逻辑日志,只记录操作,不记录数据,主要用来做主从复制和数据恢复 是在server层完成的

一个更新语句的执行流程是:先经过server层,然后交给存储引擎层执行更新,将更新结果写入到Buffer Pool,记录redo log的记录并且设置状态为prepare的,然后返回给server层,server层写入bin log日志,此时再通知存储引擎层更改redo log的状态为commit,保持数据一致性

Innodb 辅助索引只存储索引和主键值 ,主键索引即聚簇索引是和数据放在一起的

Myisam 索引和数据是分开存储的

mysql innodb如果没有主键:第一个不为空唯一索引 --》row_id

9. 事务的几种数据特性 / 事务并发带来的几个问题

  • 脏读

    A事务读到了B事务更改后但未提交的值,导致两次读取到的数据不一样

  • 不可重复读

    A事务读到了B事务更改(特指修改或者删除)后提交的值,导致两次读取的数据不一样,

  • 幻读

    A事务读到了B事务更改(特指新增)后提交的值,导致两次读取的数据不一样

10. 事务的4个隔离级别

  • RU (Read Uncommitted)未提交读

  • RC (Read Committed) 已提交读

    通过MVCC实现读一致性 通过Record lock 实现写一致性,存在幻读问题

  • RR (Repeatable Read)可重复读 同一个事务里多次读取同样的数据结果是一样的,解决了不可重复读问题,并在INNODB中解决了幻读的问题,通过临键锁,

    通过MVCC实现读一致性,通过Record Lock,Gap Lock, Next-Key Lock实现写一致性

  • Serializable 串行化 所有的事务都是串行执行的,解决了所有问题,但效率降低

11. Mysql默认添加的几个字段

  • DB_TRX_ID 事务id
  • DB_ROLL_PTR 回滚id 指向undo log
  • DB_ROW_ID 行id

12. mysql锁

包括有排它锁 即Exclusive Lock 即X锁 写锁 和 共享锁 Share Mode Lock 即S锁 读锁

  • record lock 记录锁

    如果查询的数据正好是唯一索引或者主键索引的数据,就是记录锁,只锁当前这一行数据

  • gap lock 间隙锁

    间隙所是记录锁的n+1个,是指记录不错的区间锁,左开右开的,如果查询的记录不存在,则用间隙锁

  • Next-key Lock 临键锁 默认

    临键锁是INNODB默认的行锁,并通过此解决了在RR事务级别下的数据幻读问题,如果查询的是区间数据并且命中了某一个索引的值,则用间隙锁,锁住当前记录的前一个间隙锁和后一个间隙锁。

13. mysql几种日志文件格式及作用

  • redo log 重做日志 。是存储引擎层记录的,在数据更新到Buffer Pool之后记录在redo log中,用于记录数据的更新值
  • undo log 回滚日志,也是存储引擎层记录的,用于记录数据更新前的值,
  • bin log server层记录的,只记录增删改的这些sql日志,并不记录实际的值,用于主从同步和数据恢复的

14. MySQL多版本控制MVCC

​ Multi Version Concurrency, 基于快照实现, 通过数据库隐藏的字段 事务id和 回滚指针来完成,回滚指针指向undo log里的数据

15. 如何解决数据库读一致性的问题

  1. LBCC (Lock Based Conconrrency Control)

    在读取数据前,对其加锁,阻止其他事务对数据进行修改

  2. MVCC( Muti Version Concurrency Control )

    生成一个数据请求时间点的快照,并用这个快照来提供一定级别的一致性读取

16. 二叉搜索树 二叉平衡树(AVL)B树 B+树

  • 二叉搜索树:左子树小于根节点 右子树大于根节点 按照中序排列的话是一个有序的队列,缺点是树的深度太大

  • 二叉平衡树:基于二叉搜索树的一个平衡树 树的深度绝对值差不超过1

  • B树 :多路平衡树,度是关键字n的n+1个,叶子节点都存储数据和索引,度数多

  • B+树:非叶子节点只存储关键字,不存储索引和值,所以可以存储更多关键字,叶子节点中有一个指向下一个节点的指针,排序和范围查询更快,而且树的深度是固定的,所以IO次数是固定的

17. 死锁的四大必要条件(举例说明,如何发生一个死锁)

  • 互斥条件
  • 持有且等待
  • 不可剥夺
  • 循环依赖

18. 哪些情况不走索引

1、查询条件中使用了计算 比如 age+=20

2、查询条件中使用了函数

3、第三是like %

4、or操作

以上是关于MySql常见问题的主要内容,如果未能解决你的问题,请参考以下文章

mysql 间隙锁和临键锁原理

MySQL的间隙锁

mysql间隙锁

mysql间隙锁

MySQL里的间隙锁以及加锁规则

如何在 MySQL 记录集中找到 ID 间隙?