qiuyadong's Homepage

mysql-1


一条查询语句的执行流程!一条更新语句的执行流程!事务隔离!索引!

一条查询语句的执行流程

  • 连接器

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表

只适合与等值查询,范围查询就需要全表扫描了;无序的;



Similar Posts

Comments