一条查询语句的执行流程!一条更新语句的执行流程!事务隔离!索引!
一条查询语句的执行流程
- 连接器
alias mysql=/usr/local/bin/mysql
mysql -u root -p
show processList
show variables like ‘wait_timeout’;# 2880 = 48*60小时
- 查询缓存
默认是禁止,常规的数据库命中率低,更新语句会清空缓存数据;除非静态表,系统配置表;
query_cache_type = demand ;默认
mysql 8.0 删除了该模块;
-
分析器 你要做什么?
词法解析器:字符串代表的含义,并识别出来 语法解析器:是否满足mysql规范,如拼写问题
-
优化器 该怎么做?
同一条语句有不同的执行逻辑,优化器决定使用哪个逻辑,方案合理;
-
执行器 如何执行
首先看你用户有没有此表的权限; 根据表的引擎,去使用引擎提供的接口; 可以在慢查询日志里找到row_examined字段,语句的扫描行数;
一条更新语句的执行流程
同样:连接器–> 分析器–> 优化器–> 执行器
不一样的内容如下:
-
WAL write-ahead logging 先写日志再写磁盘
redo log:是个环有write pos(当前写的位置) 和 check point(擦除的位置)组成;之间是可以写数据的内容;追上之后需要先擦数据就是持久化到磁盘再写redo log;只要有redo log;就不担心重启;
innodb 引擎独有
、引擎层的日志
、物理日志,记录某个数据页做了什么修改
,循环写的,空间固定能用完
innodb_flush_log_at_trx_commit:1 每次提交事务都持久化到磁盘。保证mysql重启不丢失;
binlog:
server层的日志
,用于归档(自带的)
,逻辑日志
,追加写,不会覆盖
; sync_binlog:1;每次提交事务持久化到磁盘,保证binlog不丢失; -
流程
内存中查数据; 没有就加载到内存; 内存中更新后记录到redo log,状态是prepare状态; 告知执行器执行完成可以提交事务了; 生成binlog日志,并把binlog写入磁盘; 执行器引擎提交事务接口,把redo log改为commit状态;
事务隔离
show variables like ‘tx_isolation’; # REPEATABLE-READ
事务:一组数据库操作,要么都成功,要么到不成功;
ACID:原子性、一致性、隔离性、持久性;
多个事务同时执行,可能出现:脏读、不可重复读、幻读;
为了解决这些问题,隔离级别:读未提交、读提交、可重复读、串行化;
-
读未提交
一个事务未提交,它的变更在另一个事务里看到了;
-
读提交
一个事务提交之后,它的变更在另一个事务里看到了;
-
可重复读
一个事务执行过程中看到的数据,总是跟这个事务启动时看到的数据一致;
-
串行化
写加写锁,读加读锁,一个事务一个事务执行;
-
视图的概念 可重复读:在事务开始的时候创建一个视图,整个期间使用这个视图; 读提交:在创建这个查询语句的时候创建一个视图; 读未提交:没有这个视图的概念; 串行化直接加锁避免并行访问;
-
回滚日志
每一个事务都有自己的视图,保存到回滚日志,每一个事务都保留一个回滚日志;
当系统中没有比这个回滚日志更早的视图的时候,回滚日志就会被删掉;
不要建长事务,回滚日志会影响性能、占用锁资源;
set autocommit=0;
begin/start transaction;
commit/rollback;
查询长事务: select * from information_schema.innodb_trx where TIME_TO_SEC(timediff(now(),trx_started))>60;
索引
- hash表
只适合与等值查询,范围查询就需要全表扫描了;无序的;