当前位置: 首页 > news >正文

MYSQL 笔记

1、索引失效的原因
参考链接:https://juejin.cn/post/7161964571853815822#heading-23
联合索引未遵循最左前缀法则
查询范围过大:like 左侧模糊匹配、in查询范围大于百分之30、select *
对索引使用聚合函数
优化器的选择导致失效:order by避免回表消耗,直接走全表扫描
字段不确定导致索引失效:使用or查询时左边有索引,右边没有

索引使用不正确:联合索引没有遵循最左前缀法则
查询范围过大,优化器生成执行任务的时候走全表扫描,in查询范围大于30%、select *、orderBy
对索引进行运算
字段的不确定性,左侧模糊匹配、or左侧有索引右侧没有

2、explain 分析执行计划
关注的字段:type、possiblekeys、keys、extra
type:system(扫系统表)、ref(非唯一索引,即返回的数据不止一条、联合索引)、range(范围查询)、Index(全索引扫描,例如不满足最左前缀)、const(唯一索引的等值匹配)、ALL(没用索引)
extra:Using Where+Using Index(走索引覆盖,但不符合最左前缀)Using Index(索引覆盖)、Using IndexCondition(走索引下推)
3、慢 SQL 优化
常见原因:没用索引、索引失效(没遵循最左前缀、区分度不高)、索引范围过大走全表、多表联查、深分页。
举例:我在开发优惠查询优惠券的时候发现接口响应得1秒多,然后我去打开慢查询日志(slow_query_log)定位到了SQL语句,发现我在用户领取优惠券表里面创建的索引是(优惠券ID、用户ID),此时用explain看了一下执行计划,发现type是Index,这意味这走全索引扫描了,因为我配置文件里面写的是按照用户ID来查的,然后我改了一下联合索引,再执行explain发现type变成ref,正常走联合索引了。
慢查询日志-定位SQL-explain(type:ref\range\index\const\all extra: Using Index Using IndexCondition

索引下推(Index Condition Pushdown):Mysql 5.6 之后新加特性,只适合二级索引,经常与联合索引一起使用。以往的查询是服务层把SQL给引擎层,引擎层根据第一索引字段去匹配值,然后每一条匹配的索引都去回表查询。现在的查询是引擎层会对联合索引中的索引值都进行筛选,筛选后的数据进行回表,减少回表的次数。
4、MYSQL集群架构
https://developer.aliyun.com/article/1169490
可用性设计:保证高可用的核心思想是冗余设计,例如服务冗余、节点冗余、数据冗余(表设计),缺点是资源压力与数据一致性问题。
数据库集群架构:
主从模式:一主多从、主从复制、读写分离。实现高可用架构,可以做读写分离与数据备份(从库备份),基于binlog做数据同步。缺点是数据同步延时、主节点故障切从需要时间。
双主模式:一主多从模式发生单点故障切从需要时间,所以做两个主节点提升主库的可用性。两个主节点互为主备,默认使用一台写数据,另一台备用并且与从节点做数据同步。缺点是双主的复制逻辑比较复杂。
分库分表:
主从同步延时如何优化?
1、如果业务能接受延时则忽略
2、读写都走主
3、半同步复制:主库至少同步一个从节点后返回。
4、cache key 控制选择性读主节点:对于不容许出现不一致的数据,更新的时候缓存key在redis中,value就是更新的时间戳,如果查询时发现有key则读主,如果没有key则读从。
5、数据库中间件选择性读主:中间件维护一个同步窗口,窗口内是写操作的key,如果还在窗口内则强制读主,否则走从库。

5、update语句执行流程

SQL语句基于TCP/IP协议的连接发送到SQL server层,server曾通过分析器解析SQL语句,检查语法错误。然后交给优化器,优化器会根据IO成本与CPU成本来生成最优的执行计划,执行器调用引擎层接口来执行计划。
引擎层加载数据(以page为单位)到Buffer Pool里面并且对数据上锁,记录undolog(SQL语句执行之前的数据信息),然后执行器更改数据信息,同时会把数据更改之后的信息记录到redo log buffer里。此外在server层执行器会生成binlog文件。
由Master线程进行事务提交,分为两阶段提交。第一阶段将内部事务XID写入redolog,并将redolog状态改为prepare并刷盘,第二阶段,执行器将内部事务XID写入binlog,进行刷盘,然后更改redolog的状态为commit。
其中redolog和binlog的刷盘策略有三种:0-不刷盘、1-同步刷盘、2-刷入os pache,由os决定何时刷盘。

6、事务的ACID
原子性:事务,由undolog保证
一致性:由AID三个属性保证
隔离性:由MVCC保证
持久性:由redolog保证
7、undolog、redolog、binlog
undolog:
记录数据修改之前的状态,InnoDB引擎生成的
当磁盘中的数据页加载到缓冲区之后,修改缓冲区的数据页的内容时,会将数据更改之前的内容、或者SQL的反操作记录在undolog内,用于事务回滚,保证事务的原子性,此外也用于支持MVCC。
undolog是全量存储的,会记录每一次操作前的所有数据,记录的内容和操作的种类有关,例如update操作,则会记录一行旧的数据,并且有两个隐藏字段:操作的事务ID、回滚指针(指向它的上一个旧数据)。
undolog分为insert undolog(记录insert语句)和 update undolog(记录update和delete语句)。insert undolog在事务提交之后就不需要了,会被删除;update undolog还需要保证MVCC做快照读,不能被立即清理。
InnoDB后台会开purge线程清理insert undolog,对于update undolog会查看是否被其他事务依赖,若没有则清理。
redolog:
记录数据修改之后的状态,InnoDB引擎生成的
当改写完缓冲区的数据页后,脏页数据如果没来得及刷盘,数据库就宕机了将导致缓冲区的数据丢失,因此在更改完数据页之后会将更改后的内容记录到redolog里面(这就是WAL技术,先记录日志再刷盘)。如果事务提交之后崩溃或者数据库宕机,可以使用redolog恢复数据,保证事务的持久性。
刷盘策略:取决于innodb_flush_log_at_trx+commit的配置。
如果配置为0,就是提交事务时不刷盘。
如果配置为1,就是提交事务时必须刷盘
如果配置为2,就是线刷进操作系统缓冲区,由系统决定啥时刷盘(例如1s一次)
binlog:
show variables like "log_bin%";
记录表字段与数据修改之后的状态,Server层生成的
binlog属于,因此不同引擎的数据库都可以使用,binlog用于主从复制。binlog有三种模式:STATEMENT、ROW、MIXED
STATEMENT: 只记录SQL语句而记录数据变化,优点在于减少日志体积,缺点在于对于uuid这种函数,每次执行生成的结果都不相同。
ROW: 记录数据修改的具体内容,优点是可靠性高,缺点是体积大。
MIXED:以上两种的混合;系统自动判断用哪种,一般语句用STATEMENT,对于可能存在二义性的语句使用ROW

如果数据库全被擦除了,如何恢复:
不可以用redolog恢复,因为redolog是循环写,只会保留未刷盘的数据。需要用binlog,因为它是全量日志。

8、binlog与主从同步:
master节点在事务提交的第二个阶段会将binlog刷盘,slave节点会使用IO线程监听binlog变化,然后请求同步。主节点开一个dump线程发送同步数据,从节点使用relaylog接受数据,然后开一个SQL线程回放relaylog中的内容进行同步。
复制的模式:
同步复制:主节点提交事务的第二个阶段必须等到所有从节点同步完数据,响应ACK之后才向客户端响应。
异步复制:主节点提交事务,binlog刷盘之后就向客户端返回,不会等从节点响应;
半同步复制:主节点提交事务第二个阶段会等待一个从节点完成复制,再响应,不会等所有从节点完成复制。

9、如何解决主从延时:
(1)忽略
(2)强制读主库
(3)使用半同步复制:修改完主库至少同步一个从库才返回请求。
(4)cacheKey控制选择性读主库:将一致性强的数据缓存成cache的key(库-表-主键值),过期时间为主从同步的延时,当缓存没有命中的时候,先去查缓存查是否有这个key,如果没有则已经同步了,如果有则还没同步,强制查主库。
(5)数据库中间件:所有的请求都走中间件,中间件路由到主库和从库。记录路由到写库的key,根据主从同步的经验时间窗口内,如果有读请求访问中间件,就读主库,否则读从库。

10、MYSQL与Redis之间缓存一致性如何保证?
答:
(1)先更新缓存再更新数据库:如果更新数据库失败了,就会出现不一致的情况
(2)先更新数据库再更新缓存:缓存没来得及更新,读操作直接读缓存就会存在不一致的问题
(3)先更新数据库再删缓存:线程B更新数据库->线程A读缓存->线程B删除缓存。
(4)先删缓存再更新数据库:线程A读数据库->线程B更新数据库->线程B删除缓存->线程B更新数据库->线程A更新缓存。
采用的办法:延时双删+定时任务:线程B更新数据库->线程B删除缓存,然后开一个延时任务去删除缓存,可以是JDK延时任务,也可以是
(5)用消息队列(可以重试来保证高可用性)监听数据库的binlog,如果害怕MQ宕机,那就两个都安排。
11、MYSQL的存储引擎
存储引擎就是管理存储数据,构建索引,进行插入、查询、更新、删除等操作。MYSQL的存储引擎分为三种:
MYISAM、INNODB、MEMERY三种,只有INNODB支持事务、外键和细粒度更高的行级锁。MYISAM仅支持表级锁基于内存存储的,查询快断电之后会丢内存。INNODB支持的是表级锁。
MYISAM:
底层数据结构是B+ Tree,但是MYISAM不支持聚族索引,因为它的索引和数据分开放,叶子节点存的是数据的地址。每次查数据都会有两次查询过程。
不支持事务
只支持表级锁
优点就在于占用空间小,缺点是不支持事务。
INNODB:
底层数据结构是B+ Tree,支持聚族索引。
支持事务
支持行级锁、外键、事务
MEMERY:基于内存存储的,断电会丢数据,使用哈希索引
用B+Tree作为索引的数据结构有三个要点:
一、它是平衡树,二、非叶子节点存放的是索引,这样可以存放更多索引,三、叶子节点上,如果是聚族索引,存放的是主键和这一行的数据,如果是普通索引,存放的是索引和主键id。叶子节点按照索引大小顺序存放,叶子节点之间通过双向链表相连支持范围查询。
B+Tree的好处:
1、非叶子节点不存数据,可以存更多的索引值,这样三层就能存2000万条数据。
2、叶子节点大小为固定的页(一个page 16KB),方便进行页分裂与合并,并且可以利用磁盘预读特性提前读到内存buffer pool里,减少磁盘IO。
3、底层按照索引值大小顺序存放,便于排序(orderby)与范围查询。 时间复杂度是O(logN)、空间复杂度O(N)
唯一索引:
插入数据前都会检查是否有重复,所以这里耗费时间和性能。由于唯一性,所以查询起来比普通索引快。缺点就是每次更新操作都要删除旧值,再插入新值。
为什么不用红黑树orB数:
主要的原因是B+树叶子节点基于双向链表存储,支持范围查询、排序优化和磁盘预读。
为什么不用hash表:
hash的优势在于增删数据,维护的成本低,B+树增删数据设计页合并与页分裂。
B+树的优势在于支持排序与范围索引,而且hash范围查询的时候,它的数值不是连续存储的,会产生随机IO,消耗性能
InnoDB最小存储单位是页:
MYSQL是最小存储单位是一个页,这样设计的好处可以从时间维度和空间维度理解,首先我们认为当前被访问的数值在未来很有可能被访问,因此会把这个页记载到内存中去进行修改,其次认为这个数据附近的数据也可能需要进行访问,所以加载的是一个页。
InnoDB与MYISAM的文件存储结构:
InnoDB:
.frm文件:表描述文件,存储表的元数据信息,和存储引擎无关。
.ibd文件:存储表的数据与索引信息。其中有共享表空间和独立表空间
共享:将表数据分成多个文件存储,优点是分文件存储,内存不受限,缺点是删除数据会出现内存碎片,查询也麻烦。
独立
:将表数据存储在一份文件中,优点是方便进行空间回收与数据迁移,缺点是单份文件存储空间受限。
12、数据库死锁问题
原因:多个事务互相等待对方的资源释放从而导致一种僵持现象。
死锁的形成条件:
互斥条件(资源的锁)、占有并等待、不可抢占、循环等待
排查办法:
1、查看死锁日志进行死锁排查:SHOW ENGINE INNODB STATUS;
2、使用SQL ServerProfiler排查死锁:
3、使用数据库性能监控工具:Prometheus+Grafana
避免死锁:
1、尽量缩短事务的执行时间,精简事务逻辑,减少锁的占有时间:在一个事务中可以将上锁语句靠后,因为事务只有在commit之后才会释放锁
2、保持一致的锁定顺序:死锁往往是多个事务以不同的顺序请求资源引发的,所以事务尽可能以相同的顺序加锁
3、MYSQL本身也有一些机制可以处理死锁问题,例如:定时轮询发现死锁问题直接中止并回滚事务,如果一个事务获取锁等待时间过长,则回滚事务。
4、减少锁的粒度,尽可能使用行级锁而不是表级锁。也可以选择合适的索引,减少上锁的范围

13、MYSQL数据类型
答:
varchar:4.0一下 varchar(20)就是20个字符,一个汉字三个字符,5.0以上varchar(20)就是20个字符。最大支持2^16个字节。
14、MYSQL的MVCC机制
答:多版本并发控制是维护数据行的多个版本,以此来解决并发情况下的读写、写写操作的冲突的,并且实现读未提交、读已提交、可重复读、串行化四个隔离级别,从而依次解决脏读、不可重复读、幻读的现象。
它是基于Read View和UndoLog实现的。
ReadView判断当前最新数据对事务是否可见、Undolog则是解决当前数据对事务不可见的时候找历史数据。
具体来说,在RC隔离机制下,事务会在每次执行查询语句的时候生成ReadView(当前读),RR隔离机制下,事务会在事务开启之后第一次查询时生成数据(快照读),只有本事务中update数据才能更新快照,否则整个事务里都是用这一个数据快照。
RR隔离级别下:普通的select语句使用的是快照读。而执行select...for update、delete、update等语句时,使用的是当前读(即最新数据),并且对数据加间隙锁。
ReadView的作用是判断哪些数据能读,哪些数据不能读。它由四个关键的要素组成:创建快照的事务ID、事务开启时还在活跃的ID集合、活跃ID集合中最小事务ID值、下一个事务的ID值。在普通查询语句中,有聚族索引的数据行中会有两个隐藏的字段,一个是最新修改的事务ID、一个是回滚指针。普通的查询语句会根据修改数据的最新ID和当前事务的ID做比较来决定当前事务是否能看到这行数据,如果最新修改事务的ID小于当前事务ID,则能看到,如果大于下一个事务的ID值,则看不到,如果在中间,则需要到生成快照读时依然活跃的事务ID集合中去找是否有这个ID,如果有,则看不到,如果没有则能看到。如果说经过一番对比发现这个数据当前事务是看不到的,它就会根据回滚指针去寻找数据的历史版本,直到满足之前的条件,如果还是找不到就会返回空。
15、MYSQL中RR隔离级别可以解决幻读吗?
答:
幻读的定义:在一个事务内,一开始查询的时候数据不存在,后续进行更新或者插入操作,又发现这个数据是存在的。
对于快照读:MVCC机制可以保证快照读的情况下不会产生幻读问题,因为ReadView可以保证不会看到不该看的数据。
对于当前读:不可能完全解决幻读问题,当执行加锁select、update、insert语句的时候属于当前读,会读取最新的数据,并且会对当前记录已经查询范围的间隙都加锁,这样可以防止其他事务插入数据。
但是!特殊情况在于,如果事务A一开始是查询数据发现不存在,事务B插入原本不存在的数据,而事务A后面又更新了这条数据的值,那么事务A的快照读里面就会更新这条数据,事务A就能查到这条数据了。
解决办法:下下策就是在一开始就加间隙锁,但是间隙锁也可可能导致死锁问题。
16、MYSQL选啥隔离级别?
MYSQL并发事务下三大问题:脏读、不可重复度、幻读
答:RC,第一、RC只会加记录锁而不会加间隙锁和临键锁,这样可以提升并发性能。第二没有间隙锁和临建锁可以减少死锁。第三、RC可以解决脏读,但是处理不了不可重复读,那就在更新的时候加乐观锁标记,加锁的时候带上乐观锁标记更新。
17、MYSQL的锁
锁的级别:共享锁(I锁)、排他锁(X锁)
锁的粒度:全局锁、表锁、行锁
全局锁:锁整个数据库实例,一般用于数据库备份
表锁:意向锁、AUTO_INC锁、字典锁
意向锁:用于解决不同粒度锁之间的冲突(粒度相同则互斥),(例如一个事务加行锁,另一个事务不需要逐行扫描而是根据意向锁来判断锁兼容性),意向锁不是锁资源,而是MYSQL对所有要加锁的事务的一种通知。它也不是用户手动加锁,而是MYSQL自动管理。
AUTO_INC锁:事务在含有自增列的表中插入数据,就会锁住整张表,等事务插入数据结束之后再释放(MYSQL 5.1之后)
字典锁:MDL锁,锁住元数据的,防止DDL操作冲突。
行锁:记录锁、间隙锁、临键锁。
记录锁:锁住主键与非主键索引。
例如:select c1 from t where c=1 for update;
间隙锁:锁住多个索引之间的间隙,无法插入数据
例如:select c1 from t where c>=1 for update;相当于锁住c=1以及后面的数据。
临键锁:锁住索引记录与一个间隙,左开右闭。
是否显示上锁:悲观锁(直接加锁)、乐观锁(CAS操作)。

update语句加的什么锁?
MYSQL的InnoDB引擎的默认锁机制是行级锁。
当update语句where后面跟唯一索引时,这一行记录对应的主键索引和非主键索引都要上锁,只是上锁的先后顺序不一样而已。对于主键索引上锁是原子性,非主键索引上锁不是原子性。容易产生死锁。
当update语句where后面没跟索引,直接锁表,为了避免这种情况可以在sql_safe_updates参数设置为1,即为安全更新模式。update语句使用where的时候必须有索引列才能执行成功;此外也可以使用force index(index name)来强制优化器走索引
但是不是where后面加了索引就走记录锁,最终还是要看MYSQL优化器走全表扫描还是索引,当然也可以通过force index(index name)来强制让InnoDB引擎走索引。
18、MYSQL的存储:
https://www.cnblogs.com/grasp/p/18265172
char、varchar区别
TLV
MYSQL数据怎么存
4个字节是数据长度
序列化是什么?
page里能存多少?行格式是咋样的?
用户数据是一个链表,查的时候是链表搜索,用跳表二分查找数据降低时间复杂度。数据越来越多,不一定是15/16

内存管理、任务调度、IO、文件管理
操作系统配置cache,
偏向锁

19、构建组合索引咋写SQL
INDEX index_name (column1, column2, column3)

CREATE INDEX idx_customer_order_date ON orders (customer_id, order_date);
20、MYSQL的索引与表数据的存储
存储引擎是InnoDB的话,.frm是表结构, .ibd是表数据和索引文件
21、常见数据结构做为索引
B+树、B树、B-树、全文索引、Hash索引
22、MYSQL各个关键字的执行顺序
from、join on 、where 、groupby、having、select、distinct、orderby、limit
23、orderby怎么实现的
因为orderby是倒数第二个执行的,先执行前面的where等条件,然后把过滤后的元素放到sort buffer里面根据指定的字段排序,如果sort buffer空间不够,会采用另一种临时文件夹的方式进行排序,临时文件夹用归并排序,就是先把数据拆分到多个子文件夹里,排完序再合并到成一个结果集返回。
查询OPTIMIZER TRACE查看是否使用临时文件夹,可以看到辅助文件数、参与排序的行数等信息
24、redis缓存的设计模式
1、旁路缓存:常用形式,适合读请求比较多的情况。先读缓存,缓存没有就读数据库,读完数据库写到缓存再返回。
2、读写穿透:
写穿透:先查cache是否存在,cache不存在则直接更新DB;cache如果存在,则先更新cache再由cache同步更新DB
读穿透:先查cache是否存在,cache存在则直接返回;cache如果不存在,则先读DB,写道cache里再返回
3、异步缓存写入:和读写穿透类似,但是是只更新缓存,异步批量的更新DB。会导致较大的数据一致问题
25、redis过期删除策略和内存淘汰策略
过期删除:用来删除过期的key定时删除、惰性删除
内存淘汰:redis内存满了的时候,random、lru、lfu->所有key、设置了过期时间的key
26、redolog中的WAL技术与CheckPoint技术
预写日志技术(WAL),如果每次有一个脏页就刷盘会非常影响性能,但是内存的数据如果断电可能会丢失。所以WAL技术就是事务提交的第一阶段先写redolog,防止应用宕机导致数据丢失。
checkPoint技术就是在redolog file中找到一个位置,把这个位置之前的页都刷新到磁盘里去,这个位置就是检查点。它是为了解决:缓冲池不够用或者redolog不够用的时候把脏页刷盘;缩短数据库的恢复时间(如果redolog很大,恢复要很长时间)。
27、binlog和redolog
binlog(二进制日志)属于Server层,记录数据变化的,它是一种逻辑日志,记录的是SQL语句的原始逻辑,并且是追加写。一般是用于归档和数据同步的。
redolog(重写日志)属于引擎层,记录事务更改后的数据,它是一种物理日志(在某一页上进行了怎样的修改),并且是循环写,被刷盘的内容后续会被覆盖,它主要是应对crash-safe,保证持久性。
28、数据库的三大范式
1NF:每一列都是原子性,不可在再分。
2NF:1NF的基础上,每张表都有一个主键作为唯一标识,且其他数据和完全依赖于主键。
3NF:2NF的基础上,消除依赖传递,也就是一个非主键值不依赖于另一个非主键值。
29、MYSQL的基本数据类型
数值类型:
整型:TINYINT: -128~127 (一个字节),一般用于存枚举类型
SMALLINT:两个字节
MEDIUMINT:三个字节
INT:四个字节
BIGINT:八个字节,其中bigint(20),占用内存依然8字节,20指的是显式的宽度,如果指定了zerofill,则会用0补齐到20位。
浮点性:
FLOAT:四个字节,单精度浮点型
DOUBLE:八个字节,双精度浮点型
DECIMAL(M,D):M>D则为M+2,否则D+2;
日期和时间类型:
DATE:YYYY-MM-DD
DATETIME:YYYY-MM-DD hh:mm:ss
字符串类型:
CHAR(n):如果是latin编码则一个字符占用一个字节,如果是utf-8编码则一个字符占1~4个字节。用于存储定长字符串,不管存什么内容都会固定占用内存。
VARCHAR(n):最小占用一个字节(存储长度),占用内存和实际存的值有关。
30、SQL优化
索引层面:
单表索引不超过5个
联合索引中区分度最高和使用最频繁的字段放在左侧
where中的字段加索引,orderBy与GroupBy的字段建立索引,因为 n j 索引下已经对orderBy索引排好顺序了,不用额外排序
SQL语句层面:
不使用select *,防止查询范围过大走全表扫描
不对索引字段用聚合函数
模糊查询不在左侧进行模糊匹配
or语句的左右都要有索引,in查询范围超过30%也会走全表
join查询尽量小表驱动大表,因为执行器会将小表加入内存,在大表中查小表的数据节约时间
合并表的时候,如果数据可以重复,建议使用union all代替union,因为union会自动去重,耗时。
表结构层面:
将经常使用的字段放到一张表
使用反范式设计,在表中增加冗余字段避免多表联查
优先选择符合存储需求,并且占用内存最小的类型,例如类型选择tinyint即可
避免使用TEXT、BLOB(文本和图片),表中尽量只存文件地址,把大文件单独放到一张扩展表中。
避免使用null值,创建表格的时候设置为not null
不使用字符串存储日期,因为字符串占用空间大,进行日期比较时效率低
单表不要包含太多字段
业务优化:
对于T+1报表数据不应该实时计算,而是在业务低峰期计算好
架构优化:
读写分离、分库分表、热点数据缓存(一致性问题)、分布式数据库
31、MYSQL事务两阶段提交
prepare阶段:将内部事务ID写入redo log,同时将redolog事务状态设为prepare,再将redolog刷盘。
commit阶段:将内部事务ID写入binlog,将binlog刷盘;将redolog事务状态设为commit,将redolog刷到os cache,由os刷盘。
为什么需要两阶段提交:
如果只有一个阶段会导致数据不一致。
先redolog再binlog,中间宕机从库无法收到新增信息;
先binlog再redolog,中间宕机主库无法进行崩溃恢复,从库多数据。
两阶段提交的问题:
磁盘IO次数高:redolog和binlog都是同步刷盘
锁竞争激烈:多个事务提交时,需要保证提交的顺序。
事务提交方式-组提交:
binlog组提交机制(group commit),将多个binlog刷盘操作合并成一个。
具体针对commit阶段进行组提交:
https://blog.csdn.net/weixin_63566550/article/details/129819638
flush阶段:多个事务按照进入的顺序将binlog从cache写入binlog文件。
sync阶段:将一组binlog文件做fsync操作
commit阶段:每个事务按顺序进行commit
其中flush、sync、commit三个阶段有各自的队列,队列首部为Leader,其余为Follower,这样上锁只需要锁单个阶段对应的队列,并发度更高。
32、orderBy使用的排序算法:
MYSQL为每个线程都分配了一个sort buffer,当排序内容容量<sort buffer时,内部排序使用快速排序;当排序内容容量>sort buffer时,外部排序先将内容均分到各个小文件中,在小文件中排序再合并成大文件,外部排序使用归并排序。
两种排序的时间复杂度都是O(nlogn)。
33、什么时候使用索引
对于唯一字段建索引,这种字段区分度高
对经常查询的字段建立索引(联合索引)
对于groupBy和orderBy建立索引,因为B+树叶子节点已经排好序,可以减少排序成本。
34、MYSQL的三层架构
连接层:建立TCP连接,对传输过来的账号密码做身份认证、权限获取。连接成功之后会分配一个线程专门和客户端进行交互,所以这里有连接池(线程池)。
服务层:主要有SQL Interface,其中包括解析器(语法解析)、优化器(生成最优的执行计划)、执行器(根据执行计划调用引擎层的接口进行crud)
引擎层:与数据进行交互,包括数据IO、对数据加锁、维护索引、生成undolog与redolog
35、为什么建表一定要有主键ID?
建表规约:
必备三字段:主键ID、创建时间、更新时间。
主键的定义与特征:
主键自增、非空、唯一、且与业务无关,尽量不变动。
主键为什么自增:
插入数据的时候如果主键id是随机的,可能需要插入到此前的数据页里,进而会从磁盘中加载数据到缓存,然后产生页分裂。如果主键id是趋势递增的,则可以追加在当前page之后,顺序写的性能会更高。
当然也不能严格步长的递增,否则容易被窃取和推断数据。当然,在事务版本号、IM增量消息中需要严格步长递增,但是一般的订单号就不行,不然可以推断一天的单量。
如果没有主键索引:
使用第一个唯一索引;内部生成一个隐藏的索引;
为什么单独创建主键ID而不是使用业务ID:
聚簇索引中能更好的标记一行数据。
主键ID自增能保证B+树在插入与删除的时候数据紧凑;
如果使用业务ID作为主键无法保证顺序性,那么在插入数据的时候发生页分裂、页合并的概率高,影响性能。
36、索引优化
1、一张表索引字段一般不超过5个,多了占内存,建立与维护困难
2、聚族索引左侧字段应该区分度高、查询频繁
3、where orderby加的字段应该加索引,索引支持排序与范围查询
37、SQL优化
1、避免select *
2、避免对select字段进行运算
3、避免模糊查询时%在左侧
4、查询条件中的or都要有索引
5、order by查询字段要有索引
6、子查询的时候要小表驱动大表,降低查询次数
7、最左前缀法则
38、表结构优化
反范式设计,因为第三范式要求消除依赖传递,这样就需要将表的字段尽可能拆分独立,没有相互依赖。但是反范式设计可以为表格增加冗余信息,减少多表联查
还有业务优化、数据库配置升级可以提升性能。
39、分布式ID生成
1、UUID
32位16进制数,可以生成同一时空中唯一的ID,UUID生成方法有5种,例如时间戳+mac地址+随机数、时间戳+ip地址+随机数、名称空间MD5码。
优点:性能高、本地生成。
缺点:太长且占内存、信息不安全(基于MAC地址生成的UUID容易被定位)。
2、雪花算法
64位二进制数,由符号位、时间戳、数据中心标识、机器标识、序列号
优点:趋势递增、生成ID的QPS高、可以根据业务特性灵活分配bit位
缺点:强依赖机器始终,时钟回拨可能造成ID重复。
解决办法:
美团使用Zookeeper解决始终回拨,每一个Leaf(服务端)定时向Zk上报时间戳,每次服务启动先校验上次生成ID的时间戳、再校验所有机器的平均时间戳。
百度UidGenerator不依赖机器时间戳,而是

http://www.hskmm.com/?act=detail&tid=9562

相关文章:

  • Java笔记
  • 分布式 笔记
  • Windows Server 2019 中文版、英文版下载 (2025 年 9 月更新)
  • Windows Server 2016 中文版、英文版下载 (2025 年 9 月更新)
  • Windows Server 2025 中文版、英文版下载 (2025 年 9 月更新)
  • 美联储降息 25 个基点,这事儿跟我们有多大关系?
  • Windows Server 2022 中文版、英文版下载 (2025 年 9 月更新)
  • 袋鼠云跻身榜单2025中国Data+AI创新企业榜Top15,入选“2025中国隐形独角兽500强”榜单等多项荣誉
  • k8s系列--前世今生
  • excel文本改为数据格式
  • 面向对象初步接触-学生信息管理系统
  • Numpy高维数组的索引()
  • 详细介绍:jQuery 操作指南:从 DOM 操作到 AJAX
  • 一个 Blazor/WinForm 开发者的 WPF 学习记:通往 Avalonia 的那条路
  • VulkanAPI细节梳理2
  • React 状态丢失:组件 key 用错引发的渲染异常 - 指南
  • 快速实现 Excel 表格转 SVG:Java 教程 - E
  • 绕过文件上传限制实现客户端路径遍历漏洞利用的技术解析
  • 事件总线之初步学习
  • Markdown Day04
  • C++中类的内存存储
  • PyTorch 优化器(Optimizer)
  • 实用指南:域名市场中,如何确认域名的价值
  • 初步了解Neo4j
  • 多模态和语音 AI 年度收官大会,把握 2026 技术风向标!
  • 做题
  • 解码C语言函数
  • SchemaStore
  • XSS攻击防御
  • imes开发部署