导图社区 Mysql45讲-逐步更新
这是一篇关于Mysql 45讲-逐步更新、我们在这篇文章里讨论的是没有过滤条件的count(*),如果加了where 条件的话,MyISAM表也是不能返回得这么快的。
编辑于2023-02-01 19:22:44 上海Mysql 45讲
2023-02-01
01 | 基础架构:一条SQL查询语句是如何执行的?
1.基础架构

1. server
1.连接器
1.管理连接,权限验证
1. 执行语句前要先连接数据库
update T set c=c+1 where ID=2;
2.查询缓存
在一个表上,有更新的时候,查询缓存就失效,这条语句就会把所有的查询缓存结果清空,一般不建议使用查询缓存。
2.缓存查询
3.分析器
3.词法分析,语法分析
3.分析器会通过词法和语法解析知道这是一条更新语句
4.优化器
4.按执行计划生成,索引选择
4. 优化器觉得使用ID这个索引。
5.执行器
操作引擎,返\回结果
5. 执行器负责具体执行,找到这一行,然后更新
6.以及所有的内置函数(如日期,时间,数学和加密函数)
7.所有跨存储引擎的功能都在这一层实现,如存储过程,触发器,视图
概要
2. 存储引擎层
负责数据的存储与提取。插件式。
1.InnoDB
2.MyISAM
3.Memory
存储数据,提供读写接口
02 | 日志系统:一条SQL更新语句是如何执行的?
执行流程图
 你执行语句前要先连接数据库,这是连接器的工作。 前面我们说过,在一个表上有更新的时候,跟这个表有关的查询缓存会失效,所以这条语句就会 把表T上所有缓存结果都清空。这也就是我们一般不建议使用查询缓存的原因。 接下来,分析器会通过词法和语法解析知道这是一条更新语句。优化器决定要使用ID这个索引。 然后,执行器负责具体执行,找到这一行,然后更新。 与查询流程不一样的是,更新流程还涉及两个重要的日志模块,它们正是我们今天要讨论的主 角:redo log(重做日志)和 binlog(归档日志)。如果接触MySQL,那这两个词肯定是绕不过 的,我后面的内容里也会不断地和你强调。不过话说回来,redo log和binlog在设计上有很多有 意思的地方,这些设计思路也可以用到你自己的程序里。
log

redolog
1. 存储引擎,InnoDB
1. redo log用于保证crash-safe能力
2.innodb_flush_log_at_trx_commit这个参数设置成1的时候, 表示每次事务的redo log都直接持久化到磁盘。这个参数我建议你设置成1,这样可以保证 MySQL异常重启之后数据不丢失。
binlog
1.Server
1.sync_binlog这个参数设置成1的时候,表示每次事务的binlog都持久化到磁盘。这
2.设置成1,这样可以保证MySQL异常重启之后binlog不丢失。
redolog binlog 区别
1. redo log是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用。 2. redo log是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的 是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。 3. redo log是循环写的,空间固定会用完;binlog是可以追加写入的。“追加写”是指binlog文件 写到一定大小后会切换到下一个,并不会覆盖以前的日志
redolog
1. redo log是InnoDB引擎特有的
2. redo log是物理日志,记录的是“在某个数据页上做了什么修改”
3. redo log是循环写的,空间固定会用完
redo ,循环写
binlog
1.binlog是MySQL的Server层实现的,所有引擎都可以使用。
2.binlog是逻辑日志,记录的 是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1 ”。
3.binlog是可以追加写入的。“追加写”是指binlog文件 写到一定大小后会切换到下一个,并不会覆盖以前的日志
两阶段提交
03 | 事务隔离:为什么你改了我还看不见?
1.事务特性
A. 原子性
C. 一致性
I. 隔离性
D. 持久性
2.隔离级别
 一若隔离级别是“读未提交”: 则V1的值就是2。这时候事务B虽然还没有提交,但是结果已经被 A看到了。因此,V2、V3也都是2。 若隔离级别是“可重复读”,则V1、V2是1,V3是2。之所以V2还是1,遵循的就是这个要求: 事务在执行期间看到的数据前后必须是一致的。 若隔离级别是“串行化”,则在事务B执行“将1改成2”的时候,会被锁住。直到事务A提交后, 事务B才可以继续执行。所以从A的角度看, V1、V2值是1,V3的值是2。
1.读未提交 (一个事务还没提交时,它做的变更就能被别的事务看到)
若隔离级别是“读未提交”, 则V1的值就是2。这时候事务B虽然还没有提交,但是结果已经被 A看到了。因此,V2、V3也都是2。
隔离 级别下直接返回记录上的最新值,没有视图概念
若隔离级别是
“ 读未提交 , 则 V1 的值就是 2 。这时候事务 B 虽然还没有提交,但是结果已经被
A
看到了。因此, V2 V3 也都是 2
2.读提交(一个事务提交之后,它做的变更才会被其他事务看到)(Oracle 默认)
若隔离级别是“可重复读”,则V1、V2是1,V3是2。之所以V2还是1,遵循的就是这个要求: 事务在执行期间看到的数据前后必须是一致的
在每个SQL语句开始执行的时候创建的
3.可重复读(一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一 致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。) mysql 默认
若隔离级别是“可重复读”,则V1、V2是1,V3是2。之所以V2还是1,遵循的就是这个要求: 事务在执行期间看到的数据前后必须是一致的。 假设一个值从1被按顺序改成了2、3、4,在回滚日志里面就会有类似下面的记录。 
视图是在事务启动时创建的,整个事务存在期间都用这个视图
4.串行化(同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突 的时候,后访问的事务必须等前一个事务执行完成,才能继续执行)
若隔离级别是“串行化”,则在事务B执行“将1改成2”的时候,会被锁住。直到事务A提交后, 事务B才可以继续执行。所以从A的角度看, V1、V2值是1,V3的值是2。
用加锁的方式来避 免并行访问。
04 | 深入浅出索引(上)
1.索引常见模型
1.哈希表
1.哈希表这种结构适用于只有等值查询的场景(Memcached及其他一些NoSQL引 擎。)
2.有序树
 有序数组索引只适用于静态存储引擎;比你要保存的是2017年某个城市的所有人口 信息,这类不会再修改的数据。
有序数组在等值查询和范围查询场景中的性能就都非常优秀
3.搜索树
2.索引类别
主键索引,非主键索引 
主键索引
主键索引也被称为聚簇索引(clustered index)。
主键索引的叶子节点存的是整行数据。
非主键索引,普通索引
主键长度越小,普通索引的叶子节点就越小,普通索引占用的空间也就越小。 显 所以,从性能和存储空间方面考量,自增主键往往是更合理的选择。
非主键索引的叶子节点内容是主键的值。
在InnoDB里,非主键索引也被称为二级索引 (secondary index)
问题:基于主键索引和普通索引的查询有什么区 基 别?
如果语句是select *fromTwhere ID=500,即主键查询方式,则只需要搜索ID这棵B+树; 如果语句是select *fromTwhere k=5,即普通索引查询方式,则需要先搜索k索引树,得到ID 的值为500,再到ID索引树搜索一次。这个过程称为回表。 也就是说,基于非主键索引的查询需要多扫描一棵索引树。因此,我们在应用中应该尽量使用主键查询
回表
3. 索引维护
4.为啥索引使用B+树?
1. B+树能够很好地配合磁盘的读写特性,减少单次查询的磁盘访问次数
2.由于InnoDB是索引组织表,一般情况下我会建议你创建一个自增主键,这样非主键索引占用的 空间最小。但事无绝对,我也跟你讨论了使用业务逻辑字段做主键的应用场景。
05 | 深入浅出索引(下)
1. 回表
  在这个例子中,由于查询结果所需要的数据只在主键索引上有,所以不得不回表。那么,有没有 可能经过索引优化,避免回表过程呢 回到主键索称为回表回 。可以看到,这个查询过程读了k 索引树的3条记录(步骤1、3和5),回表了两次(步骤2和4)。
主键索引(聚蔟索引)
非主键索引()
2.覆盖索引
如果执行的语句是select ID fromTwhere k between 3 and 5, 这时只需要查ID的值,而ID的值已经在k索引树上了,因此可以直接提供查询结果,不需要回表。 也就是说,在这个查询里面, 索引k已经“覆盖了”我们的查询需求,我们称为覆盖索引
1.由于覆盖索引可以减少树的搜索次数,显著提升查询性能,所以使用覆盖索引是一个常用 由的性能优化手段。
案例
基于上面覆盖索引的说明,我们来讨论一个问题: : 在一个市民信息表上,是否有必要将身份 在 证号和名字建立联合索引 ? 假设这个市民表的定义是这样的:  我们知道,身份证号是市民的唯一标识。也就是说,如果有根据身份证号查询市民信息的需求, 我们只要在身份证号字段上建立索引就够了。而再建立一个(身份证号、姓名)的联合索引,是 不是浪费空间? 如果现在有一个高频请求,要根据市民的身份证号查询他的姓名,这个联合索引就有意义了。它 可以在这个高频请求上用到覆盖索引,不再需要回表查整行记录,减少语句的执行时间。 当然,索引字段的维护总是有代价的。因此,在建立冗余索引来支持覆盖索引时就需要权衡考虑 了。这正是业务DBA,或者称为业务数据架构师的工作。
3. 索引 最左前缀原则
标注
1.B+B 树这种索引结构,可以利用索引的 树 “最左前缀 最 ”,来定位记录
为了直观地说明这个概念,我们用(name,age)这个联合索引来分析。 
4. 索引下推优化(index condition pushdown)
可以在索引遍历过程中,对索 引中包含的字段先做判断,直接过滤掉不满足条件的记录,减少回表次数。

6.全局锁和表锁 :给表加个字段怎么有这么多阻碍?
锁类别
1.全局锁
定义:全局锁就是对整个数据库实例加锁。
方法:Flush tables with read lock (FTWRL)。
使用场景: 全库备份,整库每个表select出来存成文本。
问题
主库备份,备份期间都不能执行更新,业务基本停摆。
从库备份,备份期间从库不能执行主库同步过来的binlog,会导致主从延迟。
2.表级锁
表锁语法 lock tables …read/write
释放锁
1. 主动 unlock tables主动释放锁,
2. 客户端断开的时候自动释放锁
类表级的锁是 另 MDL M (metadata lock)
不需显示使用,访问一个表的时候会被自动加上
作用:确保读写正确性
子主题
锁特点
 我们可以看到session A先启动,这时候会对表t加一个MDL读锁。由于session B需要的也是 MDL读锁,因此可以正常执行。 之后session C会被blocked,是因为session A的MDL读锁还没有释放,而session C需要MDL写 锁,因此只能被阻塞。 如果只有session C自己被阻塞还没什么关系,但是之后所有要在表t上新申请MDL读锁的请求也 会被session C阻塞。前面我们说了,所有对表的增删改查操作都需要先申请MDL读锁,就都被 锁住,等于这个表现在完全不可读写了。 如果某个表上的查询语句频繁,而且客户端有重试机制,也就是说超时后会再起一个新session 再请求的话,这个库的线程很快就会爆满。 你现在应该知道了,事务中的MDL锁,在语句执行开始时申请,但是语句结束后并不会马上释 放,而会等到整个事务提交后再释放
读锁不互斥
读写锁,读读锁互斥
3.行锁
定义
1.行锁就是针对数据表中行记录的锁
支持存储引擎
1.InnoDB 支持
2.MyISAM 不支持
两阶段锁协议
在InnoDB 事务中,行锁是在需要的时候才加上的,但并不是不需要了就立刻释 事 放,而是要等到事务结束时才释放
死锁和死锁检测
死锁案例

应对策略
1.直接进入等待,直到超时 ;innodb_lock_wait_timeout来设置。 默认50s
2. 发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事 务得以继续执行。 将参数innodb_deadlock_detect设置为on,表示开启这个逻辑
主动死锁检测,
innodb_deadlock_detect = on
问题:怎么解决由这种热点行更新导致的性能问题呢?问题的症结 在于,死锁检测要耗费大量的CPU资源?
1.一种头痛医头的方法,就是如果你能确保这个业务一定不会出现死锁,可以临时把死锁检 一测关掉。
但是这种操作本身带有一定的风险,因为业务设计的时候一般不会把死锁当做一个严 重错误,毕竟出现死锁了,就回滚,然后通过业务重试一般就没问题了,这是业务无损的。而关 掉死锁检测意味着可能会出现大量的超时,这是业务有损的。
2.控制并发度
根据上面的分析,你会发现如果并发能够控制住,比如同一行同时 最多只有10个线程在更新,那么死锁检测的成本很低,就不会出现这个问题。一个直接的想法 就是,在客户端做并发控制。但是,你会很快发现这个方法不太可行,因为客户端很多。我见过 一个应用,有600个客户端,这样即使每个客户端控制到只有5个并发线程,汇总到数据库服务 端以后,峰值并发数也可能要达到3000。 因此,这个并发控制要做在数据库服务端。如果你有中间件,可以考虑在中间件实现;如果你的 团队有能修改MySQL源码的人,也可以做在MySQL里面。基本思路就是,对于相同行的更新, 在进入引擎之前排队。这样在InnoDB内部就不会有大量的死锁检测工作了
7.行锁功过:怎么减少行锁对性能的影响?
子主题
子主题
子主题
08 | 事务到底是隔离的还是不隔离的?
案例
A 事务执行过程: 
视图
view
一个是view。它是一个用查询语句定义的虚拟表,在调用的时候执行查询语句并生成结果。 创建视图的语法是create view…,而它的查询方法与表一样。
read view
InnoDB在实现MVCC时用到的一致性读视图,即consistent read view,用于支持 RC(Read Committed,读提交)和RR(Repeatable Read,可重复读)隔离级别的实现.
“快照快 ”在MVCC里是怎么工作的?

1.transaction id
1.InnoDB里面每个事务有一个唯一的事务ID,叫作transaction id。在事务开始的时候向 InnoDB的事务系统申请的,是按申请顺序严格递增的
2. rowtrx_id
而每行数据也都是有多个版本的。每次事务更新数据的时候,都会生成一个新的数据版本,并且 把transaction id赋值给这个数据版本的事务ID,记为rowtrx_id。同时,旧的数据版本要保留, 并且在新的数据版本中,能够有信息可以直接拿到它
3. undo_log
图2中的三个虚线箭头,就是undo log;而V1、V2、V3并不是物理上真实存在的,而 是每次需要的时候根据当前版本和undo log计算出来的。比如,需要V2的时候,就是通过V4依 次执行U3、U2算出来
前事务的一致性视图(read-view)
视图数组
高水位
 1. 如果落在绿色部分,表示这个版本是已提交的事务或者是当前事务自己生成的,这个数据是 可见的; 2. 如果落在红色部分,表示这个版本是由将来启动的事务生成的,是肯定不可见的; 3. 如果落在黄色部分,那就包括两种情况 a. 若 rowtrx_id在数组中,表示这个版本是由还没提交的事务生成的,不可见; b. 若 rowtrx_id不在数组中,表示这个版本是已经提交了的事务生成的,可见。 比如,对于图2中的数据来说,如果有一个事务,它的低水位是18,那么当它访问这一行数据 时,就会从V4通过U3计算出V3,所以在它看来,这一行的值是11。 你看,有了这个声明后,系统里面随后发生的更新,是不是就跟这个事务看到的内容无关了呢? 因为之后的更新,生成的版本一定属于上面的2或者3(a)的情况,而对它来说,这些新的数据版 本是不存在的,所以这个事务的快照,就是“静态”的了
InnoDB为每个事务构造了一个数组,用来保存这个事务启动瞬间,当前正在“活 跃”的所有事务ID。“活跃”指的就是,启动了但还没提交
数组里面事务ID的最小值记为低水位,当前系统里面已经创建过的事务ID的最大值加1记为高水 位
09 | 普通索引和唯一索引,应该怎么选择?
10 | MySQL为什么有时候会选错索引?
MysqlBug
1.索引选择由优化器来完成
2.索引选择异常与处理
1.像我们第一个例子一样,采用force index 强行选择一个索引
2.我们可以考虑修改语句,引导MySQL使用我们期望的索引
3.创建一个更合适的索引,来提供给优化器做选择,或删掉误用的索引
子主题
11 | 怎么给字符串字段加索引?
11 | 怎么给字符串字段加索引?
1.使用前缀索引,定义好长度,就可以做到既节省空间,又不用额外增加太多的查询成本
2.案例
1.身份证查询
1.前6位相同,前缀索引没有意义
2.前12索引,索引选取越长,占用的空间就越大,相同的数据也能放下的索引值就越少,搜索的效率就越低
3.解决办法
1.身份证倒序存储

2.使用hash字段, 创建一个整数字段,来保存身份证验证码,同时在这个字段上创建索引。

总结:

1.直接创建完整索引,这样可能比较占用空间;
2.创建前缀索引,节省空间,但会增加查询扫描次数,并且不能使用覆盖索引;
3.倒序存储,再创建前缀索引,用于绕过字符串本身前缀的区分度不够的问题;
4.创建hash字段索引,查询性能稳定,有额外的存储和计算消耗,跟第三种方式一样,都不支持范围扫描。
子主题
子主题
12|为什么我们MySQL会“抖”一下?
主题
14 | count(*)这么慢,我该怎么办?
1.MySQL引擎中,count(*)有不同的实现方式。
MyISAM引擎把一个表的总行数存在了磁盘上,因此执行count(*)的时候会直接返回这个数, 效率很高;
我们在这篇文章里讨论的是没有过滤条件的count(*),如果加了where 条件 的话,MyISAM表也是不能返回得这么快的。
而InnoDB引擎就麻烦了,它执行count(*)的时候,需要把数据一行一行地从引擎里面读出 来,然后累积计数
子主题
子主题
2.那为什么 为 InnoDB I 不跟不 MyISAM M 一样,也把数字存起来呢?
 这是因为即使是在同一个时刻的多个查询,由于多版本并发控制(MVCC)的原因, InnoDB表“应该返回多少行”也是不确定的。 这里,我用一个算count(*)的例子来为你解释一下。 假设表t中现在有10000条记录,我们设计了三个用户并行的会话。 会话A先启动事务并查询一次表的总行数; 会话B启动事务,插入一行后记录后,查询表的总行数; 会话C先启动一个单独的语句,插入一行记录后,查询表的总行数。 我们假设从上到下是按照时间顺序执行的,同一行语句是在同一时刻执行的。 图1 会话A、B、C的执行流程  你会看到,在最后一个时刻,三个会话A、B、C会同时查询表t的总行数,但拿到的结果却不 同。 这和InnoDB的事务设计有关系,可重复读是它默认的隔离级别,在代码上就是通过多版本并发 控制,也就是MVCC来实现的。每一行记录都要判断自己是否对这个会话可见,因此对于 count(*)请求来说,InnoDB只好把数据一行一行地读出依次判断,可见的行才能够用于计算“基于这个查询”的表的总行数
3.总结

1.MyISAM表虽然count(*)很快,但是不支持事务;
2.showtable status命令虽然返回很快,但是不准确
3.InnoDB表直接count(*)会遍历全表,虽然结果准确,但会导致性能问题。
我们这篇文章要解决的问题,都是由于InnoDB要支持事务,从而导致InnoDB表不能把count(*) 直接存起来,然后查询的时候直接返回形成的。
15 | 答疑文章(一):日志和索引相关问题
追 1:MySQL怎么知道 怎 binlog是完整的 是 ?
回答:一个事务的binlog是有完整格式的:statement格式的binlog,最后会有COMMIT; row格式的binlog,最后会有一个XID event。 另外,在MySQL 5.6.2版本以后,还引入了binlog-checksum参数,用来验证binlog内容的正确 性。 对于binlog日志由于磁盘原因,可能会在日志中间出错的情况, MySQL可以通过校验checksum的结果来发现。 所以,MySQL还是有办法验证事务binlog的完整性的。
追 2:redo log 和 binlog是怎么关联起来的 是 ?
回答:它们有一个共同的数据字段,叫XID。崩溃恢复的时候,会按顺序扫描redo log: 如果碰到既有prepare、又有commit的redo log,就直接提交; 如果碰到只有parepare、而没有commit的redo log,就拿着XID去binlog找对应的事务。
追 3:处于 : prepare阶段的 阶 redo log加上完整 加 binlog,重启就能恢 , 复,复 MySQL为什么要这么设计 为 ?
回答:其实,这个问题还是跟我们在反证法中说到的数据与备份的一致性有关。 在时刻B,也就是binlog写完以后MySQL发生崩溃,这时候binlog已经写入了,之后就会被从库(或者用这个 binlog恢复出来的库)使用。 所以,在主库上也要提交这个事务。采用这个策略,主库和备库的数据就保证了一致性。
结合三:追问追 4:如果这样的话,为什么还要两阶段提交呢?干脆先 : redo log写完,再写 写 binlog。崩溃恢复的时候,必须得两个日志都完整才可以。是不是一样的逻辑?
回答:其实,两阶段提交是经典的分布式系统问题,并不是MySQL独有的。 如果必须要举一个场景,来说明这么做的必要性的话,那就是事务的持久性问题。 对于InnoDB引擎来说,如果redo log提交完成了,事务就不能回滚(如果这还允许回滚,就可能覆盖掉别的事务的更新)。 而如果redo log直接提交,然后binlog写入的时候失败,InnoDB又回滚不了,数据和binlog日志又不一致了。 两阶段提交就是为了给所有人一个机会,当每个人都说“我ok”的时候,再一起提交。
追 5:不引入两个日志,也就没有两阶段提交的必要了。只用 : binlog来支持崩 来 溃恢复,又能支持归档,不就可以了?
回答:这位同学的意思是,只保留binlog,然后可以把提交流程改成这样:…-> “数据更新到内存” -> “写 binlog” -> “提交事务”,是不是也可以提供崩溃恢复的能力? 答案是不可以。 如果说历史原因 历 的话,那就是InnoDB并不是MySQL的原生存储引擎。 MySQL的原生引擎是MyISAM,设计之初就有没有支持崩溃恢复。 InnoDB在作为MySQL的插件加入MySQL引擎家族之前,就已经是一个提供了崩溃恢复和事务支持的引擎了。 InnoDB接入了MySQL后,发现既然binlog没有崩溃恢复的能力,那就用InnoDB原有的redo log好了。 而如果说实现上的原因 实 的话,就有很多了。就按照问题中说的,只用binlog来实现崩溃恢复的流程,我画了一张示意图,这里就没有redo log  这样的流程下,binlog还是不能支持崩溃恢复的。我说一个不支持的点吧:binlog没有能力恢 复“数据页”。 如果在图中标的位置,也就是binlog2写完了,但是整个事务还没有commit的时候,MySQL发生了crash。 重启后,引擎内部事务2会回滚,然后应用binlog2可以补回来;但是对于事务1来说,系统已经认为提交完成了,不会再应用一次binlog1。 但是,InnoDB引擎使用的是WAL技术,执行事务的时候,写完内存和日志,事务就算完成了。 如果之后崩溃,要依赖于日志来恢复数据页。 也就是说在图中这个位置发生崩溃的话,事务1也是可能丢失了的,而且是数据页级的丢失。此时,binlog里面并没有记录数据页的更新细节,是补不回来的。 你如果要说,那我优化一下binlog的内容,让它来记录数据页的更改可以吗?但,这其实就是又做了一个redo log出来。 所以,至少现在的binlog能力,还不能支持崩溃恢复。
追 6:那能不能反过来,只用 : redo log,不要 , binlog?
回答: 如果只从崩溃恢复的角度来讲是可以的。你可以把binlog关掉,这样就没有两阶段提交 了,但系统依然是crash-safe的。 但是,如果你了解一下业界各个公司的使用场景的话,就会发现在正式的生产库上,binlog都是开着的。因为binlog有着redo log无法替代的功能。 一个是归档。redo log是循环写,写到末尾是要回到开头继续写的。这样历史日志没法保 留,redo log也就起不到归档的作用。 一个就是MySQL系统依赖于binlog。 binlog作为MySQL一开始就有的功能,被用在了很多地方。 其中,MySQL系统高可用的基础,就是binlog复制。 还有很多公司有异构系统(比如一些数据分析系统),这些系统就靠消费MySQL的binlog来更新自己的数据。 关掉binlog的话,这些下游系统就没法输入了。 总之,由于现在包括MySQL高可用在内的很多系统机制都依赖于binlog, 所以“鸠占鹊巢”redo log还做不到。你看,发展生态是多么重要。
追 7:redo log一般设置多大?
追 7:redo log一般设置多大? 一 回答:redo log太小的话,会导致很快就被写满,然后不得不强行刷redo log,这样WAL机制的能力就发挥不出来了。 所以,如果是现在常见的几个TB的磁盘的话,就不要太小气了,直接将redo log设置为4个文 件、每个文件1GB吧
追 8:正常运行中的实例,数据写入后的最终落盘,是从 : redo log更新过来的 更 还是从 还 buffer pool更新过来的呢? 更
子主题
16 | “order by”是怎么工作的?
1.排序
 city='杭州' 索引; 
1.初始化sort_buffer,确定放入name,city ,age字段
2.从索引city找到第一个满足city='杭州'的主键id,也就是图中ID_X;
3.到主键id索引取出整行,取name,city ,age三个字段的值,存入sort_buffer中
4.从索引city中取下一个记录的主键ID
5.重复步骤3,4直到city的值不满足查询条件为止,对应的主键id也就是图中的ID_Y
6.对sort_buffer中的数据按照字段name做快速排序
7.按照排序结果取前1000行返回给客户端
概要

2.rowid排序
3.总结,排序过程,参考1排序
16 | “order by”是怎么工作的?
17 | 如何正确地显示随机消息?
18 | 为什么这些SQL语句逻辑相同, 性能却差异巨大?
案例一:条件字段函数操作
案例二: 隐式类型转换
案例三: 隐式字符编码转换
utf8mb4;  UTF8 
字符集utf8mb4是utf8的超集,内部比较的时候,转换操作
1.相当于对traideid 进行了函数转换

子主题
子主题
19 | 为什么我只查一行的语句, 也执行这么慢?
1.查询长时间不返回

被锁了, show processlisg
2.查询慢

全表扫描
20 | 幻读是什么, 幻读有什么问题?
幻读是什么?

一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。
幻读有什么问题?
1.首先语义
2其次,是数据一致性的问题
如何解决幻读?

子主题
主题
主题
主题