Mysql

48 阅读5分钟

基础

第一范式是列不能再细分,第二范式是必须有主键即一个表描述一件事,第三范式是不能有冗余字段 

架构

连接器的并发查询数不包括pending线程 

缓存已删除 

分析器做语法分析 

优化器做索引选择,主要依据是索引基数,即索引区分度,计算基数使用采样索引统计 

执行器判断对表的权限 

存储引擎提供读写接口 

redolog WAL实现crash-safa,是循环写,三种写入策略分别写入0buffer,2page以及1磁盘 

undolog用于回滚 

binlog格式包括,statement,row以及mix,row使用校验和验证数据完整性,mix时会判断statement会不会造成主备数据不一致,和redolog保持双1配置,即事务提交前redolog和binlog都同步到磁盘 

relaylog用于重放 redolog的两阶段提交指在事务提交前,需要先依次提交redolog的prepare以及binlog以及redolog的commit,保证redolog和binlog的数据一致性,binglog通过checksum校验完整性,完整则提交redolog不完整则不提交redolog 

组提交表示一起提交多个事务的redolog,leader事务提交时会带上组内最大的LSN 

更新逻辑即刷脏页,redolog满时会刷脏页 

视图

隐藏数据复杂性 

权限

用户权限,DB权限,表权限 

分区表

有一个frm文件和多个ibd文件 

建表

多对多的关系用中间表表达,一对多的关系用明细表表达 

存储引擎

innodb支持行级锁 

Myisam索引和数据不在同一个文件,而innodb的主键索引和数据都在同一个文件 

memory内存表应用于临时表场景 

事务

InnoDB实现 

ACID:A undoLog实现;c AID实现;I 隔离级别实现;D redolog的WAL实现 

显示事务启动时在第一条语句才启动 

传播行为 support required 

隔离级别 可重复读是mysql,快照读MVCC,当前读更新时使用,幻读由next-key解决 

全局锁:FTWRL和read_only 

表锁:MDL 

Myisam:不会死锁 

InnoDB:间隙锁,可重复读,读提交+binglog=row,next-key解决幻读 

悲观锁:以上都是 

MVCC:readview,回滚+版本可见性:视图数组低水位 

死锁:循环等待,冲突行后置 

可重复读加锁:单位是next-key,等值查询在唯一索引和普通索引的优化 

索引

约束:两个约束会自动创建索引 

自增主键:不是连续的,因为一次申请多次且不会回退 

自增ID用完时,表ID保持不变,还有rowID,XID,视图数组的trx_id以及thread_id4种ID 

索引缺点是索引维护 

索引维护会导致页分裂,自增主键少一点,业务逐渐多一点,索引重建使数据紧凑 

change_buffer降低读IO,redoLogBuffer降低写IO,由于change_buffer的原因,尽量选择普通索引 

联合索引:最左匹配,优化有跳跃索引和ICP 

InnoDB的索引模型有BTree和AHI哈希索引,哈希索引只适用于等值比较 

优化

通过查询health表或者查询内部统计表判断数据库是否异常 

使用where代替having以及使用覆盖索引避免索引失效 

查询慢的原因之一是别的线程执行大量更新导致快照回滚,还有一种有损方案就是查询重写 

深分页可以使用子查询或者limit优化为利用索引 

因为null不适用于不等于条件,所以字段尽量为not null 

分表字段的选择依据为避免数据倾斜,分表算法有根据数值划分,哈希取模或者一致性哈希,全局ID的方案有UUID,单表加步长以及雪花。分表方案带来的问题就是读扩散问题 

读写分离方案的问题在于过期读,解决方案可以是判断主库无延迟才开放从库读,无延迟指标有位点,GTID以及SBM指标 

主备是实现读写分离的方案,原理就是备库的io和sql两个线程 

主备延迟可以使用并行复制,即将sql线程改为IO多路复用模型,后面挂一些worker线程,并行度可以是按表分发,按行分发 

主备切换有可靠性优先和可用性优先,可靠性优先可以判断SBM指标 

主从切换可以基于GTID,主库将与从库GTID之间的差集发给从库 

临时表

临时表可以与普通表重名,因为临时表结构在物理和内存中存储都会带上线程ID 

临时表的使用场景如union和group by,union因为需要保证唯一性,而group by因为分组条件需要单独存储,group by在没有聚合函数时等同于distinct 

sql

DQL的行转列有wmconcat,listagg以及pivot 

全表扫描对server层会占满netBuffer,对存储引擎会导致buffer pool全是冷数据,inndoDB对bufferpool做了young和old区域划分的优化 

join内部有NLJ,BNL以及BKA三种算法,NLJ和BNL一个使用了被驱动表的索引一个没有使用,BKA是对NLJ的优化,利用了MRR,即在驱动表回表前将ID在内存中排序以实现顺序读盘 

删除的性能,drop大于truncate大于delete,delete不会释放空间, 需要进行表重建 

expain可以查看执行计划,extra列展示了执行过程中的操作 

kill 命令不管是关闭查询还是连接,都不是立即关闭,只是发送信号给阻塞中的线程 

对于count函数,myISAM是单独存储,而innodb需要查询,查询耗时count(col)大于count(id)大于count(1)等于count(*0),当然也可以使用计数表和redis等方案计数 

order by内部利用了sortBuffer排序,使用的堆排序,全字段排序不用回表rowid需要回表,优先使用全字段排序,行数据量大于阈值则会变为rowid排序