【MySQL 45讲笔记】

第一讲:一条SQL查询语句是如何执行的?

  • 连接器:在完成了经典的TCP握手后,开始认证身份,以及校验权限
  • 分析器:词法分析和语法分析
  • 优化器:使用哪个索引、各个表的连接顺序
  • 执行器:调用引擎接口取数据,判断是否符合条件,符合条件的放在结果集
  • 存储引擎:与磁盘交互,获取数据,返回给执行器

第二讲:一条SQL更新语句是如何执行的?

两个重要日志

  • bin log:server层、追加写、记录更新SQL语句
  • redo log:存储引擎、覆盖写、记录更新数据

更新过程

  • redo log - prepare:更新数据记录到内存
  • bin log:更新语句记录到磁盘
  • redo log - commit:更新数据记录到磁盘

第三讲:事务隔离,为什么你改了我还看不见

事务执行语句

  • 事务启动语句:begin、start transaction
  • 事务提交语句:commit
  • 事务回滚语句:rollback
  • 自动提交关闭:set autocommit = 0

第四讲:深入浅出索引(上)

创建索引语句

create table T(
	id int primary key,
	k int not null,
	name varchar(16),
	index(k)
)engine = InnoDB;

主键索引和普通索引的区别

  • 主键索引不需要回表。普通索引如果没有覆盖索引就需要回表

第五讲:深入浅出索引(下)

几个重要的概念

  • 覆盖索引:普通索引如果是覆盖索引,那就不用回表
  • 最左前缀原则:索引内的多个字段从左到右,字段的内容也是从做到右
  • 索引下推:可以减少回表次数

第六讲:全局锁和表锁,给表加个字段怎么有这么多阻碍?

全局锁

  • 全局读锁命令:Flush tables with read lock
  • 典型使用场景:全库逻辑备份

表级锁

  • 表锁(数据锁):lock tables t1 read, t2 write;(加锁)、unlock table;(解锁)
  • 元数据锁MDL(表结构锁):不需要显式使用,在访问一个表的时候就会被自动加上

行级锁

  • MySQL的行级锁是在引擎层由各个引擎自己实现的,但并不是所有的引擎都支持行锁

第七讲:行锁功过,怎么减少行锁对性能的影响?

重要概念

  • 两阶段锁:上锁阶段和解锁阶段
  • 死锁:两阶段锁会导致死锁

死锁解决

  • 设置死锁超时:innodb_lock_wait_timeout = 50
  • 设置死锁检测:innodb_deadlock_detect = on
  • 控制并发度:控制操作同一行数据的线程数
  • 将一行改成逻辑上的多行来减少锁冲突

第八讲:事务到底是隔离的还是不隔离的?

两种读

  • 当前读:读最新提交的数据
  • 一致性读:遵循隔离机制来读取数据

不同操作的隔离机制

  • 更新操作:读已提交(当前读)
  • 查询操作:可重复读(一致性读)

思考一下为什么?
事务B查到K的值是3,而事务A查到K的值是1
在这里插入图片描述

第九讲:普通索引和唯一索引,应该怎么选择?

因为唯一索引的更新操作可能无法使用change buffer,所以一般推荐选择普通索引。

第十讲:MySQL为什么有时候会选错索引?

查询索引信息

  • 命令:show index from table_name;

影响索引选择的因素

  • 扫描行数:优先选择扫描行数小的索引
  • 区分度:区分度越大,扫描行数越小
  • 回表:如果普通索引+回表消耗的性能大于全表查询,那么就会导致索引失效
  • 字段排序:

索引选择错误的解决办法

  • 执行修正命令:analyze table t;
  • 强制使用索引:select * from t force(a) where …
  • 引导使用索引:order by b变成order by b,a
  • 删除误用的索引

第十一讲:怎么给字符串字段加索引?

  • 命令:alter table user add index index_email(email6));
  • 原则:在区分度和索引长度之间权衡利弊

第十二讲:为什么我的MySQL会“抖”一下?

主要分为两种场景,导致MySQL突然抖一下

  • redo log写满了,要刷新redo log内存(日志写回磁盘)
  • 缓冲池buffer pool不够用了,要先将脏页写到磁盘(数据页写回磁盘)

InnoDB刷脏页的控制策略

  • 影响InnoDB刷脏页能力的因素:脏页比例、redo log写盘速度
  • 通过命令可以获取磁盘的IOPS,然后将InnoDB的innodb_io_capacity设置为IOPS
  • InnoDB的实际刷盘速度,内部计算出一个R%,然后乘以innode_io_capacity,就是刷盘速度

第十三讲:为什么表数据删掉一半,表文件大小不变?

  • delete命令其实只是把记录的位置,或者数据页标记为了“可复用”,但磁盘文件的大小是不会变的。也就是说,通过delete命令是不能回收表空间的。这些可以复用,而没有被使用的空间,看起来就像是“空洞”。

第十四讲:count(*)这么慢,我该怎么办?

  • 随着系统中记录数越来越多,select count(*) from table_name也会执行得越来越慢
  • 可以使用缓存、数据表来存储count(*)的值
  • 不同count的性能:count(字段)< count(主键id)< count(1)≈ count(*)

第十六讲:order by是怎么工作的?

select city, name, age from T where city = '杭州' order by name limit 1000;

  • 全字段排序:取出整行数据,然后取city、name、age放入sort_buffer排序,不需要回表
  • rowid排序:取出整行数据,部分字段放入sort_buffer排序,需要回表
  • 如果(city, name)是索引,那么上面的order by就不需要排序

第十七讲:为什么我只查一行的语句,也执行这么慢?

select * from table where id = 1

  • 等锁释(MDL锁、行锁)
  • 等flush刷盘

select * from table where c = 50000 limit 1

  • 查询慢:全表扫描、
  • 事务:一致性读导致的undo很多次,当前读直接读最新值

猜你喜欢

转载自blog.csdn.net/m0_46638350/article/details/132148688
今日推荐