4.2-中间件之MySQL

4.2.1MySQL的基本知识

SQL语句

用于存取数据以及查询、更新和管理关系数据库系统。包括:DQL(select)、DML(insert,update,delete)、DDL(create,alter,drop)、DCL(grant,revoke)权限验证。

MySQL体系结构

MySQL内部分层。

在最外层是server层,有几个组件组成。其中SQL Interface用于对用户发送来的sql进行词法句法分析,生成语法树。再由Parser对语法树进行过滤,比如要查询的字段在表中没有,进行报错。过滤后,由Optimizer制定执行计划,选择一个最佳的执行方案执行sql

在server层执行后,是存储引擎层,用于具体执行server层传入的执行方案。常用的存储引擎是InnoDB。

在存储引擎层下面,是文件系统层,存储着物理数据。

MySQL内部连接池

mysql会为每一个连接分配一个线程,每一个线程以阻塞io的方式进行read、do_command,各线程的处理是并发的。

MySQL执行一条select语句的过程

在网络层面,连接器接收连接,为连接分配线程。再先查询缓存(mysql8.0后已经删除这一步),若缓存没有啊,通过SQL Interface分析器组件进行词法句法分析生成语法树,再通过优化器组件制定执行方案,执行器根据执行计划,从存储引擎获取数据返回。

如果是预处理语句,比如有很多select,就可以写成select  * from user where id = ?;?用来接收参数,避免重复解析。会跳过连接器、分析器、优化器,直接进入到执行器执行计划这一步。

数据库设计的三范式

目的:避免数据冗余、允许空间占用

三范式内容:每一个列的字段,都是最简的,不可再分的。如果有多个主键,那么表中其他键都需要完全依赖主键,且与主键直接相关,而不是间接相关。如果某表不能满足上述要求,那么说明表中有冗余数据存在,需要对表进行拆分,以编号替代冗余部分。

反范式:范式可以简单理解为 “时间换空间”,牺牲多张表跳转查询的时间来避免数据冗余空间浪费。但是如果冗余字段较少且追求查询效率,可以用反范式。

MySQL删除数据的几种方式

1.drop(DDL):完全删除表,包括数据和结构,表将不存在,不可回滚

2.truncate(DDL):只删除表中数据,变成空表,其中自增约束置为初始值。不可回滚,以页为单位删除

3.delete(DML):删除部分或全部数据,可以回滚,以行为单位删除。

MySQL的高级查询

1.分组+聚合查询:通过group by对表分组后,计算sum()、avg()、max()、min()、count(),都是对分组后的各组内进行操作。

比如:select  `gender`,count(*) as num from `student` group by `gender`;

2.联表查询  

举例:查询 ‘数学’课程比‘语文’课程成绩高的所有学生的学号;

分析:涉及两张表,一个是分数表,一个是课程表。需要先从课程表中,通过课程名称cname = '数学' 查询出课程对应的cid,然后再到分数表中查询对应课程的学生id以及分数num,这样就构成了两个表A与B,分别意味着报了数学的集合,报了语文的集合,表中只有两个字段:sid与num。

再通过inner join取两张表的交集,即数学语文都报了的人,构成一张新表,最后select 数学分数高于语文分数的学生学号即可。

select A.student_id from(select student_id,num from score where course_id =(select cid from course where cname = `数学`)) as Ainner join(select student_id,num from score where course_id =(select cid from course where cname = `语文`))as Bon A.student_id = B.student_idwhere A.num > B.num;如果没报语文课程的人也算在内,那就改成left join最后一行改成where A.num > IFNULL(B.num,0);

视图是什么?

是一种虚拟存在的表,是一个逻辑表,其内容由查询定义,本身并不包含数据。

优点:向上面例子中的表构建比较麻烦,如果每次都要写这么多sql很冗余,可以直接构建一个视图,且视图的结构不会受原表的影响。

4.2.2MySQL索引原理以及SQL优化

索引是什么?

索引是一种有序的数据结构,按照单个或者多个列的值进行排序,用于提升搜索的效率。比如主键索引(非空+唯一)、唯一索引(可空)、普通索引(可空+可不唯一),组合索引(对表中多个列进行索引)。

索引常用的数据结构是B+树:

在course表中的主键索引cid,作用就相当于一个map<int , course>,根据cid找到course,其中索引cid就是聚集索引B+树中的非叶子节点,用于查找,叶子节点中存储的就是course(数据)+cid(索引)

在course表中的普通索引tid,作用就相当于一个 multimap<int ,pairs<int,int>> ,根据tid找到键值对 <索引信息,主键信息>。其中索引tid就是辅助索引B+树中的非叶子节点,用于查找,叶子节点中存储的就是索引信息 + 主键信息,要拿到完整的数据要拿到主键信息,再到聚集索引B+树中取出。但是如果要查询的信息只有主键信息,或者其他辅助索引B+树中本身就有的信息,则为覆盖查询,可以直接返回,速度很快,这也是不建议用select *,而具体写出字段名的原因,可以避免回表查询。

主键的选择

有设置primary key则当然其为主键;如果没设置则选一个非空唯一索引作为主键;如果非空唯一索引也没有,则创建一个6字节的_rowid作为主键。

MySQL是磁盘IO,索引如何保证业务高效?

1.叶子节点的连续

在通过非叶子索引节点查找到目标数据所在的页后,由于叶子节点间是有序且直接连接的,可以减少磁盘的寻道时间,直接把页从磁盘读入内存。

2.一次从磁盘中读取多个页到内存中缓存

对B+树的操作,也不会马上写回磁盘,对于change buffer,会定期合并到buffer pool中,而buffer pool中的被修改后的脏数据,会集中direct io到磁盘中

MySQL的内存安全保证

在MySQL对磁盘的操作,如果是操作的聚集索引B+树,则是先对buffer pool中的节点进行操作,如果操作的是辅助索引B+树,则是对Change buffer中的节点操作。但是如果出现断电,也不用担心内存数据丢失,没有及时刷盘导致数据错误,因为有Redo Log,aof型日志,记录buffer中的变化信息,可以恢复buffer。

组合索引在查询时候的规则:最左匹配原则

组合索引算作辅助索引。

如果将两个索引(A,B)结合成一个索引,那么在select查询的时候,会按照最左匹配原则进行查询,即select中有没有where带上A的相关限定信息,如果有,则会按照其进行排序,如果没有或者只有B的限定信息,则会进行全表查询。

索引下推是什么?

对象是辅助索引,普通索引和联合索引场景居多。

原本是在server层获得存储引擎层的数据后,根据索引条件过滤数据

索引下推机制,即将部分索引条件判断下推到存储引擎中过滤数据,最终返回给server层。

索引的作用是加速sql执行,有没有索引失效的情况?

1.select ... where A and B 若A和B中,有一个字段不是索引,则会索引失效

2.如果让索引字段参与运算,则会索引失效,如  where cid -1 = 2;

3.like 模糊查询,以 %开头,会进行全表查询,索引失效,因为B+树读取到%不知道怎么查。

4.没有遵循最左匹配原则

出现了sql比较慢的排查思路

先开启慢查询日志,找到SQL语句,然后通过explain字段,通过分析器看where、group by、order by后面的字段有没有踩索引,如果没有,看看是没有创建索引还是索引失效。如果有踩索引但是速度慢,看看能否用in 或者 not in优化成联表查询,或者如果SQL语句太大了,考虑拆分,减少联合查询。

4.2.3MySQL事务原理

事务的特性和Redis中的事务有共同性,也是在有多条连接的情况下,利用事务性保证单个连接上用户操作的不可分割。只需要在多条sql前加上 begin; 末尾加上 commit;事务的特征有:

1.原子性:undolog辅助实现原子性

2.一致性:数据库的一致性:用户处理完后比如有唯一约束的字段也不能出现重复的值。

                逻辑的一致性:没有脏读、幻读、不可重复读的问题。

3.隔离性:指并发连接间的隔离性,适当的破坏一致性。有四个隔离级别,对应着四种并发程度。

4.持久性:redolog实现持久性

四个隔离级别(由低到高)

1.读未提交:对读操作不做任何处理,对写操作自动加锁

分析:存在脏读问题。A事务写还未结束,B事务因为读无限制,看到A事务的中间结果,为脏读。

2.读已提交(RC):读操作采用MVCC策略。读到的是最新的数据,写操作自动加锁

分析:避免了脏读,A没有结束,B读不到他修改的结果。但是存在“不可重复读”问题,A事务要是在B事务结束前结束了,那么B事务会看到最新的结果,即两次B事务中的查询结果不一致。

3.可重复读(RR):读操作采用MVCC策略。读到的是事务开始前版本的数据,写操作自动加锁

分析:避免了不可重复读问题,两次查询的结果都是一样的。但是存在“幻读”问题,A事务和B事务都在执行过程中,B事务查询到没有ID为3的行数据,但紧接着A事务插入了一个ID为3的行数据,那么B事务在插入ID为3的行数据的时候,就会因为违反唯一约束而返回错误。

4.可串行化:读写都加锁

分析:解决了幻读的问题,即在B事务查询是否有ID为3的行数据的时候,加上for update字段(x锁)或者lock in share mode(S锁/共享锁)加锁,这时候A事务想要添加ID为3的行数据会阻塞,知道B事务添加ID为3的行数据并且commit后,A事务会报错。

MVCC策略

MVCC的核心思想:不加锁,为每行数据保存多个版本(快照)。当一个事务需要读取数据时,MVCC会提供一个符合该事务开始时间点的“数据快照”,而不是直接读取当前最新的、可能正在被其他事务修改的数据。​​ 这样就实现了读不加锁,读写操作通常不会互相阻塞,极大地提升了并发性能。

Read View是事务在进行快照读(普通SELECT语句)时产生的数据结构,它定义了当前事务能看到哪个版本的数据。
“读已提交RC”是在每次读取数据的时候,生成新的read_view

“可重复读RR”是在启动事务的时候,生成新的read view,一直使用到事务提交或者回滚

read view中有trx_id 、min_trx_id 、max_trx_id 、m_ids,事务间可见的情况只有:

trx_id < min_trx_id   和  min_trx_id < trx_id < max_trx_id && trx_id 不属于 m_ids

事务隔离级别的实现

利用锁机制实现,锁的类型有:行级锁(共享锁、排他锁),表级锁(意向共享锁、意向排他锁)。

锁算法有:Record记录锁(单个行记录上的锁),Gap间隙锁(锁定一个范围,全开区间),Next-Key Lock(记录所 + 间隙锁,左开右闭)

锁的对象:在RC和RR两种隔离级别下

1.行级锁是针对表的索引加锁,包括聚合索引和辅助索引

2.表级锁是针对页或者表进行加锁

3.Gap锁通常是加在RR隔离级的情况下

举例:

聚集索引,查询命中,RC和RR两种隔离级别都会对命中行加锁。

聚集索引,查询未命中,RC不加锁,RR在未命中字段的左右区间加一个gap锁

辅助非唯一索引,查询命中,RC把辅助表命中的行锁定,并且把聚合数据表中相关的行也锁定。

RR在RC的基础上,还在辅助表中,命中的两个字段,产生的三个间隙,都加gap锁。

死锁的产生

情况1:相同表不同行加锁顺序相反,比如A事务update id1 id2  ,B事务update id2 id1;update和delete操作是会自动加上锁的。解决:调整执行顺序。

情况2:锁冲突,在RR隔离级别下面,如果先持有了gap锁,再想加意向锁,就会产生锁冲突。解决:降为RC隔离级别,这样就没有gap锁了。

4.2.4MySQL缓存策略

在MySQL中,也会采用缓存,不同于buffer pool,而是一种类似Redis的内存缓存,他不仅有更快的速度,而且不像buffer pool受限于MySQL,虽然缓存中的数据必须在MySQL中存在,但是可以根据业务自定义热点数据存入缓存。可以大大降低数据库的压力,对写压力没有什么缓解,因为如果频繁写的话,我们用一个缓存还需要多考虑一致性的问题。

弊端是redis不支持事务的回滚,不能rollback,还有就是存在缓存和MySQL不一致的可能。

在引入Redis缓存后的写操作如何实现?

1.追求安全

在每次DML写操作,都先在Redis缓存中,删除对应的行(比如要修改 id = 1的年龄,先在缓存中删除id =1的行数据)。然后再到MySQL中进行操作,操作后,利用一个伪装从数据库的节点,从MySQL中拉取数据到Redis缓存中。这样可以保证在修改期间,其余用户不会读到脏数据,但是在修改前还要额外操作缓存影响效率。

2.追求效率

DML操作也对Redis执行,但是加上一个pexpire,设置过期时间如200ms,这样缓存中id=1的年龄就先被修改,随后再修改MySQL中id=1的年龄。如果MySQL中修改失败,那么Redis在200ms后也会删除这个错误的数据,如果MySQL成功,那么就会通过伪造从数据库进行数据同步。

此处的过期时间实际上 = MySQL传输时间 + MySQL处理时间 + MySQL同步时间

在这个期间内,别的用户可能会读到Redis中的脏数据。

MySQL到Redis的同步是如何实现的?

1.修改配置文件使transfer工具与MySQL和Redis建立连接。

2.配置热点数据,只拉取热点数据表的内容

3.用lua脚本设定同步的规则:怎么把MySQL的结构改成Redis的结构?transfer工具启动连接到MySQL的bin.log文件,按行读取里面的内容,改成Hash结构。获取各列的字段值,设置key后再通过Redis中的命令将各值直接HSET写入key对应的value。

还有哪些方式能提升MySQL的访问性能?

1.读写分离

MySQL也有很多salve从数据库用作备份,他们会不断的主动读取主数据库的二进制log,保持数据一致性。这样我们可以将业务的DML操作交给主数据库,而读操作提交给从数据库,分担主数据库的读压力。但是从数据库读取的数据没有强一致性,会有延迟存在,如果有强一致性需求,需要从主数据库读取。

2.数据库连接池

MySQL内部用的是select,阻塞io模型,一个连接对应一个线程,所以我们可以开启数据库连接池创建多条连接,提升并发度

3.异步连接

MySQL是阻塞IO,只会一个请求一个请求的执行,但是在服务器端我们可以设置非阻塞io,不断的给MySQL发请求,不等他连接后再发下一个。节省网络传输时间,解放服务器端核心线程。

MySQL缓存可能遇到的问题:都是源于大量请求进入到MySQL

1.缓存穿透

如果持续访问Redis和MySQL中都不存在的的数据,造成MySQL性能急剧下降

解决:

(1)对目标访问的数据在Redis中设置对应的key,nil;避免其再进一步访问MySQL

(2)在Redis上配置布隆过滤器,他能判断访问的数据是否在MySQL数据库中,如果不在拒绝访问

2.缓存击穿

比如在百亿秒杀开始前1s,Redis中的热点数据过期了,那么大量的访问就会并发进入到MySQL,造成MySQL性能急剧下降

解决:

(1)设置热点数据不过时

(2)设置分布式锁,访问Redis发现数据不存在的请求,先获取分布式锁(例如使用Redis的 SETNX 命令),成功获取的线程才能访问MySQL,这样获得锁的线程就能重建缓存,其他等待的线程也能从缓存中获取数据。

3.缓存雪崩

Redis中大量的key在同一时间内过期,大量的请求也就无法命中,导致MySQL的压力过大。相比较于缓存击穿的范围更大

解决:

(1)间隔设置过期时间

(2)在重启系统或者流量低峰期将高频访问的数据预热到缓存中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/96657.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/96657.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LVS + Keepalived 高可用负载均衡集群

目录 一、核心组件与作用 1. LVS&#xff08;Linux Virtual Server&#xff09; 2. Keepalived 二、DR 模式下的 LVS Keepalived 工作原理 1. 整体架构 2. 数据包流向&#xff08;DR 模式&#xff09; 三、部署步骤&#xff08;DR 模式&#xff09; 3.1 环境规划 3.2…

知识沉淀过于碎片化如何形成体系化框架

要将过于碎片化的知识沉淀转变为体系化的框架&#xff0c;必须采取一套自上而下设计与自下而上归集相结合的系统性方法&#xff0c;其核心路径在于首先进行战略性诊断与顶层蓝图设计、其次构建统一且可扩展的知识架构&#xff08;分类与标签体系&#xff09;、然后实施系统性的…

XLua教程之C#调用Lua

上一篇文章 XLua教程之入门篇-CSDN博客 在C#脚本中访问lua全局数据&#xff0c;特别是table以及function&#xff0c;代价比较大&#xff0c;建议尽量少做相关操作。 LuaEnv.Global.Get 用于获取一个全局变量&#xff0c;但是无法获取局部变量(用local修饰) 全局基本类型变量…

C++ 标准库中的哈希函数:从std::hash到自定义哈希器

C 标准库中的哈希函数&#xff1a;从 std::hash 到自定义哈希器 1. 引言 在上一篇中&#xff0c;我们介绍了哈希表为什么能够实现 O(1) 查找。 核心秘密在于&#xff1a;哈希函数。 在 C 标准库中&#xff0c;哈希表容器&#xff08;如 unordered_map、unordered_set&#xff0…

在图形 / 游戏开发中,为何 Pixels Per Unit(PPU)数值越小,物体在屏幕上显示的尺寸越大?

1. 什么是 PPU&#xff1f; PPU&#xff08;Pixels Per Unit&#xff09;指的是 多少像素对应游戏世界中的一个单位&#xff08;Unit&#xff09;。 在 Unity 等游戏引擎中&#xff0c;1 Unit 通常被视为世界空间的基本长度&#xff0c;比如 1 米。2. PPU 与物体大小的关系PPU …

【ZYNQ开发篇】Petalinux和电脑端的静态ip地址配置

使用Petalinux工具为ZYNQ板卡搭建嵌入式Linux操作系统&#xff0c;成功搭建后&#xff0c;用户通常会使用客户端软件对ZYNQ板卡上的Linux系统进行访问&#xff0c;软件需要知道ZYNQ板卡的ip地址才能进行访问&#xff0c;如果ip地址是动态变化的&#xff0c;软件每次访问都要重新…

AVL树知识总结

AVL树概念性质一颗AVL树或是空树&#xff0c;或者具有一下性质的二叉搜索树&#xff1a;左右都是AVL树&#xff0c;左右子树高度差的绝对值不超过1AVL树有n个结果&#xff0c;高度保持在O&#xff08;logN&#xff09; 搜索时间复杂度O(logN&#xff09;模拟实现插入定义&#…

返利app的跨域问题解决方案:CORS与反向代理在前后端分离架构中的应用

返利app的跨域问题解决方案&#xff1a;CORS与反向代理在前后端分离架构中的应用 大家好&#xff0c;我是阿可&#xff0c;微赚淘客系统及省赚客APP创始人&#xff0c;是个冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01; 在返利APP的前后端分离架构中&#xff0c;跨…

【dl】python基础 深度学习中需要用到的python基础

直接在jupyter写笔记然后导出md格式真的太好用了本文笔记来自小破站视频BV1K14y1c75ePython 基础 1. 变量 1.1 三种基本变量类型 # 字符串 str str_v "123"# 数字 int或float num_v 11 float_v 12.0# 布尔型 bool bool_v True1.1.1 字符串 f字符串&#xff1a;在…

Vue FullPage.js 完整使用指南:Vue 3 官方全屏滚动解决方案

概述 vue-fullpage.js 是 FullPage.js 的官方 Vue.js 3 包装器&#xff0c;为 Vue 3 应用提供了强大的全屏滚动功能。该插件基于成熟的 FullPage.js 库&#xff0c;支持多种滚动效果和丰富的配置选项&#xff0c;特别适用于企业级数据大屏、产品展示、单页应用等场景。 官方信…

软件工程实践一:Git 使用教程(含分支与 Gitee)

文章目录目标一、快速上手1. Windows 安装 Git2. 初始化 / 克隆二、核心概念速览三、常用命令清单1) 查看状态与差异2) 添加与提交3) 历史与回溯4) 撤销与恢复&#xff08;Git 2.23 推荐新命令&#xff09;5) 忽略文件四、分支与合并&#xff08;Branch & Merge&#xff09…

css`min()` 、`max()`、 `clamp()`

min() 用来计算多个数值中最小的那个&#xff0c;非常适合做自适应。 width: min(50vw, 500px) 50vw 表示 视口宽度的 50% 500px 表示 500px min(50vw, 500px) 表示会取两者中 最小的那个 作为最终的宽度&#xff0c;。 使用场景 限制某个元素宽度不超过某个值&#xff1b; 响…

【WRF-VPRM 预处理器】HEG 安装(服务器)-MRT工具替代

目录 HEG 安装 验证 HEG 安装与否 设置环境变量(建议) 命令行接口(Command Line Interface) hegtool 工具 hegtool 用法 Header File 格式 功能1:`gdtif` 工具 – MISR 数据处理 `gdtif` 使用方式 参数文件格式(Parameter File Format) 功能2:`resample` 工具 – 重采样…

PyTorch 神经网络

神经网络是一种模仿人脑神经元链接的计算模型&#xff0c; 由多层节点组成&#xff0c; 用于学习数据之间的复杂模式和关系。神经网络通过调整神经元之间的连接权重来优化预测结果&#xff0c;这个过程可以涉及到向前传播&#xff0c;损失计算&#xff0c;反向传播和参数更新。…

详细解析苹果iOS应用上架到App Store的完整步骤与指南

&#x1f4f1;苹果商店上架全流程详解 &#x1f469;‍&#x1f4bb;想要将你的App上架到苹果商店&#xff1f;跟随这份指南&#xff0c;一步步操作吧&#xff01; 1️⃣ 申请开发者账号&#xff1a;访问苹果开发者网站&#xff0c;注册并支付99美元年费&#xff0c;获取开发者…

三维GIS开发实战!Cesium + CZML 实现火箭飞行与分离的 3D 动态模拟

CZML是一种基于JSON的数据格式&#xff0c;专门用于在Cesium中描述3D场景和时间动态数据。本文将详细介绍了CZML的特点&#xff08;JSON格式、时间动态性、层次结构等&#xff09;和基本组件&#xff0c;并给出了一个火箭发射的实例。通过搭建Cesium开发环境&#xff08;使用vi…

Spring Boot 深入剖析:BootstrapRegistry 与 BeanDefinitionRegistry 的对比

在 Spring Boot 的启动过程中&#xff0c;BootstrapRegistry 和 BeanDefinitionRegistry 是两个名为“Registry”却扮演着截然不同角色的核心接口。理解它们的差异是深入掌握 Spring Boot 启动机制和进行高级定制开发的关键。BootstrapRegistry public static ConfigurableAppl…

贪心算法应用:速率单调调度(RMS)问题详解

Java中的贪心算法应用&#xff1a;速率单调调度(RMS)问题详解 1. 速率单调调度(RMS)概述 速率单调调度(Rate Monotonic Scheduling, RMS)是一种广泛应用于实时系统中的静态优先级调度算法&#xff0c;属于贪心算法在任务调度领域的经典应用。 1.1 基本概念 RMS基于以下原则&…

Cesium4--地形(OSGB到3DTiles)

1 OSBG OSGB&#xff08;OpenSceneGraph Binary&#xff09;是基于 OpenSceneGraph&#xff08;OSG&#xff09; 三维渲染引擎的二进制三维场景数据格式&#xff0c;广泛用于存储和传输倾斜摄影测量、BIM、点云等大规模三维模型&#xff0c;尤其在国产地理信息与智慧城市项目中…

多语言共享贩卖机投资理财共享售卖机投资理财系统

多语言共享贩卖机投资理财/共享售卖机分红/充电宝/充电桩投资理财系统 采用thinkphp内核开发&#xff0c;支持注册赠金、多级分销&#xff0c;功能很基础 修复后台用户列表管理 可自定义理财商品 多种语言还可以添加任意语言 源码开源 多级分销 注册赠金等