MySQL读书笔记

 

MySQL分层架构

Server层:涵盖MySQL大多数的核心功能,以及内置函数如存储过程、触发器、视图等
存储引擎:负责数据的存储和提取

从一条查询语句分析:

其中Server层可划分为:
  
  连接器: 负责跟客户端建立连接、获取权限、维持和管理连接
          mysql -h ip -P port -u name -p password
  
          show processlist; 查看链接 默认八小时的连接时间 wait_timeout控制
          长链接:连接成功后,客户端持续有请求,使用同一连接。
          短链接:每次执行完很少的几次操作就断开。
          推荐使用长连接 —— MySQL占用内存大 

  查询缓存: 执行查询命令之前,MySQL会先到缓存中查看,如果存在返回k-v,k为查询语句,v为查询结果
            如果不存在,继续往下执行,并把结果缓存到内存中
            
            推荐不使用查询缓存,因为查询缓存失效频繁,如果对一个表更新,那么找个表的所有的查询缓存都会被清除
            
            通过设置 query_cache_type=DEMAND 即不使用查询缓存
            设置 SQL_CACHE 显式指定
            
            select SQL_CAHCHE * from T where id=1;
            
  分析器: 如果没有命中查询缓存,则需要对SQL语句解析,分析SQL语句语法是否正确
  
  优化器: 经过分析器后,还需要经过优化器优化决定使用那个索引 多表关联的时候 每个表的顺序
  
  执行器: 经过优化器,MySQL开始执行SQL语句

从更新语句分析底层

update user set username='张三' where id=1;

简单来说更新流程同上面讲的查询流程,首先经过连接器进行权限验证、登陆操作,然后将涉及到的user表的查询缓存清空,
接着在分析器中分析语法,优化器中决定使用id这个索引,执行器去执行本条命令,然后执行更新。

其中需要主要的是在执行器还需要同InnoDB进行交互,涉及到 两阶段提交 —— 目的是让 redo_log 和 binlog日志文件一致

redo_log 记录操作到此文件中,等待InnoDB空闲时将数据写入磁盘,保证之前提交的数据不会丢失(物理日志) 直白的说就是记录了做了什么
改动
binlog Server层的日志,逻辑日志,记录sql语句的原始逻辑

先写redo_log: 先写redo_log后,如果数据库异常重启了,binlog未写完。由于redo_log能够进行恢复所以数据库中的username值为 张三
但是因为binlog里面没有这个数据,当使用binlog日志来进行恢复的时候就会出现数据不一致的情况。

先写binlog: 当先写了binlog后,数据库异常重启了,由于redo_log没写,所以数据库的username仍是原来的数据,当使用binlog恢复数据时,
多出一个将username更新为 "张三" 的事务,因此数据库又不一致了。

四个隔离级别

读未提交 -- 别人尚未提交的数据,本事务也能看到
读已提交 -- 别人已经提交的数据,本事务才能看到
可重复读 -- 别人已经提交的数据,本事务不会去读,需要保持数据一致
串行化   -- 读写均会加锁,其他事务无法修改

隔离级别从上到下并发能力越弱,安全性越高

其中数据库最常见问题存在两个脏读幻读不可重复读:
  脏读:简单来说就是针对同一数据两次读取不一致,读取到了其他事务未提交的数据。即读未提交数据!!!
  幻读:前后读取多数,数据总量不一致。
  不可重复读:针对同一数据,前后多次读取,同一数据内容不一致。
  
 区别:
  不可重复读:读取了其他事务提交的数据,对于事务而言是非正常的,应使用行锁来限制其他事务的修改(update操作)
  幻读:读取了其他事务的数据(insert、delete操作),使用表锁进行数据量确定
  

细讲索引


如何有效的删除表数据

在mysql8.0版本中存储表结构和表数据存放在一个文件中,但是在此之前两者是分开存放的。
在数据删除的时候并不是直接删除问题,只是将相关状态位置为可使用,因此数据文件大小是不会通过delete删除数据减小的。(空洞)
可通过创建临时表,将数据读出再写入避免空洞问题,减少数据文件大小。