网络及操作系统知识点汇总

一.网络相关

1.网络模型

(1)七层网络模型

     从下到上:物理层-数据链路层-网络层-传输层-会话层-表示层-应用层

(2)TCP/IP网络模型

     简化的七层模型:数据链路层-网络层-传输层-应用层

应用层,负责向用户提供一组应用程序,比如 HTTP、DNS、FTP 等;

传输层,负责端到端的通信,比如 TCP、UDP 等;

网络层,负责网络包的封装、分片、路由、转发,比如 IP、ICMP 等;

网络接口层,负责网络包在物理网络中的传输,比如网络包的封帧、MAC 寻址、差错检测,以及通过网卡传输网络帧等;

2.HTTP

(1)HTTP常见状态码

1xx,协议处理的中间状态

2xx,服务器成功处理了客户端的请求

3xx,客户端请求的资源发生了变动,需要重定向

4xx,客户端发送的报文有误,服务器无法处理(错误码)

5xx,客户端请求报文正确,但是服务器处理时内部发生了错误

(2)HTTP与HTTPS的区别

a.HTTP以明文传输数据,而HTTPS协议传输的数据是经过TLS加密后的,HTTPS具有更高的安全性;

b.HTTPS在三次握手之后还要进行SSL的handshake,用来协商加密使用的对称加密秘钥;

c.使用HTTPS协议需要服务端申请证书,浏览器端安装对应的根证书;

d.HTTP协议的端口是80,HTTPS协议的端口是443;

HTTPS的优点:因为其在数据传输过程中使用了TLS加密,所以它更安全。并且由于需要认证服务器和用户,因此可以保证数据传输的正确性

HTTPS的缺点:在握手阶段的延迟较高,因为在三次握手之外还要进行SSL握手。还有就是HTTPS的部署成本较高,需要购买CA证书,且由于涉及到数据的加解密操作,对与服务器配置的要求也会偏高。

3.TCP和UDP的区别

可靠性:TCP 提供可靠的数据传输,通过确认和重传机制、滑动窗口、超时重传等来确保数据的正确性和完整性。而UDP 则是一种无连接的协议,不提供可靠性保证,数据报文发送后即忘记,不关心是否被接收或顺序是否正确。

连接性:TCP 是面向连接的协议,建立连接后进行数据传输,保证了数据的有序性和可靠性。而UDP 是无连接的协议,每个数据包都是独立的,没有建立连接的过程。

效率:由于提供了可靠性和连接管理等功能,TCP 的开销较大,适用于对数据完整性要求较高的应用场景。UDP 则没有这些额外的开销,传输效率较高,适用于实时性要求较高的应用场景,如实时音视频传输、游戏等。

4.TCP三次握手

第一次握手,客户端向服务端发送一个SYN报文,该报文中包含一个随机生成的初始序列号(ISN)用于后续的数据传输;

第二次握手,服务器接受到客户端的SYN报文后,会发送一个ACK确认报文作为响应,此时ACK中的确认号为客户端发来的序号加1,然后也发送一个SYN报文给客户端,表明服务器已经收到了客户端的请求,该SYN中的初始序列号也是随机生成的;

第三次握手,客户端收到服务器的SYN+ACK报文后,会发送一个确认报文ACK作为响应。其中的确认号会设置为服务器发来的序号加1,表示客户端已收到服务器的回应。

只进行前两次连接服务器会发生什么?

如果TCP连接只采用两次握手,会引发一些安全和可靠性问题。

两次握手建立的连接是不可靠的。TCP是全双工的,两次握手只能确定单向链路是正常通信的,不能保证反向也是正常的。

两次握手的方式可能导致半开连接问题。比如客户端发送连接请求,但是服务端没有收到,然后客户端重新建立连接。此时服务器可能收到之前的连接请求,从而导致连接混乱

两次握手存在安全性问题。由于没有第三次握手中的随机序列号,攻击者可以更容易地伪造连接。

客户端在第二次握手的基础上,向服务器发送一个确认请求(ACK)。这个ACK中包含了服务器在前两次握手中发送给客户端的随机序列号。在收到客户端的ACK后,服务器会生成一个新的随机序列号,用于之后数据传输的序列号。

5.TCP四次挥手

首先,客户端打算关闭连接,此时会发送一个 TCP 首部 FIN 标志位被置为 1 的报文,也即 FIN 报文,之后客户端进入 FIN_WAIT_1 状态。【第一次挥手】

然后服务端接收该报文后会向客户端发送一个ACK应答报文,进入CLOSE_WAIT状态。【第二次挥手】

客户端收到服务端的确认报文后进入FIN_WAIT_2 状态,等待服务端将剩余数据处理完。

处理完剩余数据后,服务端再向客户端发送 FIN 报文,服务端进入 LAST_ACK 状态。【第三次挥手】

收到服务端的 FIN 报文后客户端会回一个ACK,之后进入 TIME_WAIT 状态。【第四次挥手】

服务端收到了 ACK 应答报文后,就进入了 CLOSE 状态,完成连接关闭。

客户端在经过 2MSL 一段时间后,自动进入 CLOSE 状态,完成连接关闭。

每个方向都需要一个 FIN 和一个 ACK,因此通常被称为四次挥手。

这里一点需要注意是:主动关闭连接的,才有 TIME_WAIT 状态。

第四次挥手ack丢失怎么办?

在TCP连接的第四次挥手过程中,如果ACK(确认)丢失,这可能会导致连接无法正常关闭,因为双方无法确认对方已经收到了关闭请求。

发生这种情况一般会使用等待超时的方法来处理。

TCP协议有一个连接超时机制,如果一段时间内没有收到对方的确认,发送方会认为数据丢失,并重新发送。等待足够长的时间,通常是几个最大段生存时间(Maximum Segment Lifetime,MSL)的时间(通常是2分钟左右,即2MSL),可能会导致连接最终关闭。

但这会导致连接保持在TIME_WAIT状态,并占用系统资源。

网络中可能存在来自发送方的数据包,当这些发送方的数据包被接收方处理后又会向对方发送响应,所以一来一回需要等待 2 倍的时间。

6.TCP怎么保证传输可靠

确认和重传机制:

TCP 采用确认和重传机制来保证数据的可靠传输。当发送方发送数据时,接收方会返回一个 ACK 确认消息,表示已经成功接收到数据。如果发送方在一定时间内没有收到确认消息,就会重新发送该数据。

滑动窗口机制:

TCP 中的滑动窗口机制可以有效地控制发送方和接收方之间的数据流量。发送方根据接收方的反馈信息来调整发送窗口大小,从而避免了数据包的拥塞和丢失。

超时重传:

如果发送方连续多次发送数据但未收到确认消息,认为该数据包可能已经丢失或损坏,就会触发超时重传机制,重新发送该数据包。

累积确认机制:

TCP 采用累积确认机制,即接收方只需要确认已经接收到的数据序列号最大的分组,就可以表明其之前所有的数据都已经正确接收。这样可以减少确认消息的传输量,提高网络吞吐量。

流量控制:

TCP 通过窗口控制机制来限制发送方的数据流量,以防止接收方无法处理过多的数据包。每个 TCP 连接都有一个接收窗口和发送窗口,用于控制发送和接收方之间的数据流量。

7.TCP的拥塞控制(快重传是怎么发生的)

    快重传是TCP拥塞控制中的一个重要机制。快重传是指当接收方收到一个已经正确接收但是序号不连续的数据包时,会立即发出重复确认(Duplicate ACK)。发送方在收到连续的3个重复确认之后,

会认为这个数据包之后的数据可能丢失,因此会马上重传该数据包,而不必等待超时计时器的触发。通过快速重传机制,TCP可以更迅速地检测到丢失的数据包,并尽早进行重传。

这样可以减少等待超时计时器触发的时间延迟,提高网络传输的效率和可靠性。

   需要注意的是,快重传只适用于丢失但有顺序的数据包。如果接收方收到乱序的数据包,则会触发超时重传,这是因为乱序的数据包可能是由于网络拥塞造成的,而不仅仅是丢失。

8.什么是重传?为什么会发生重传?

tcp实现可靠传输的方式之一就是使用序列号和确认应答。当发送端数据到达接收端主机时会返回一个确认应答消息

但是如果丢包的话某一方可能就收不到应答,因此需要重传机制来解决

常见的重传机制有:超时重传、快速重传、SACK以及D-SACK

8.如何处理粘包?

粘包是指发送方连续发送的多个小数据包在接收方处被误认为一个大数据包,或者一个大数据包被分割成多个小数据包接收。这可能会导致数据解析错误或丢失部分数据。

可以使用消息边界来解决这个问题。在应用层协议中定义明确的消息边界标识,接收方根据消息边界来区分不同的消息。例如,在报文中可以使用特殊字符或标签标识消息的开始和结束。

此外,还可以使用定长包(发送方将每个数据包都固定为相同的长度。接收方按照固定长度进行拆包和处理。如果数据不足定长,可以用填充数据补齐。)或者设定时间间隔的方式去处理。

9.ICMP协议

主要用于网络设备之间的通信,以执行网络故障排除和管理任务。ICMP 报文是封装在 IP 包里面,它工作在网络层,是 IP 协议的助手。

ICMP协议的主要功能:

错误报告:ICMP用于报告与IP数据包相关的错误和异常情况。例如,当一个路由器无法将数据包传递到目标主机时,它可以生成一个ICMP错误消息通知源主机。

网络探测:ICMP还用于执行网络探测和诊断任务。例如,Ping工具使用ICMP Echo请求和响应消息来测试主机的可达性和响应时间。

路由器通知:路由器可以使用ICMP消息来通知其他路由器或主机有关网络拓扑的变化。这对于路由表的更新和路由器的重新路由非常重要。

时间戳和网络延迟:ICMP协议支持时间戳消息,允许计算机测量网络往返时间和延迟。

10.127.0.0.1 和 localhost 以及 0.0.0.0 区别

localhost 就不叫 IP,它是一个域名(与"baidu.com"是一个形式的东西),默认会把它解析为 127.0.0.1(可以在hosts文件中设置)

127.0.0.1 是回环地址。localhost是域名,但默认等于 127.0.0.1。

0.0.0.0 , 那么它表示本机上的所有IPV4地址。

二.操作系统

1.虚拟内存

什么是虚拟内存,为什么使用虚拟内存

为了防止不同进程同一时刻在物理内存中运行而对物理内存的争夺和践踏,采用了虚拟内存。

虚拟内存技术使得不同进程在运行过程中,它所看到的是自己独自占有了当前系统的4G内存。所有进程共享同一物理内存,每个进程只把自己目前需要的虚拟内存空间映射并存储到物理内存上。

虚拟内存的好处:

(1).扩大了地址空间;

(2).内存保护(提供写保护):每个进程运行在各自的虚拟内存地址空间,互相不能干扰对方。虚存还对特定的内存地址提供写保护,可以防止代码或数据被恶意篡改;

(3).公平内存分配。采用了虚存之后,每个进程都相当于有同样大小的虚存空间;

(4).当进程通信时,可采用虚存共享的方式实现(方便实现内存共享机制);

(5).当不同的进程使用同样的代码时,比如库文件中的代码,物理内存中可以只存储一份这样的代码,不同的进程只需要把自己的虚拟内存映射过去就可以了,节省内存;

(6).方便了多任务处理:虚拟内存技术可以为每个进程提供独立的虚拟地址空间,使得多个进程之间不会相互干扰,方便了多任务处理。

虚拟内存的代价:

(1).虚存的管理需要建立很多数据结构,这些数据结构要占用额外的内存;

(2).虚拟地址到物理地址的转换,增加了指令的执行时间;

(3).页面的换入换出需要磁盘 I/0,这是很耗时的;

(4).如果一页中只有一部分数据,会浪费内存;

2.内存泄漏和内存溢出的关系

内存泄漏(Memory Leak)是指程序在分配内存后,无法释放不再使用的内存,导致系统中的可用内存逐渐减少。这最终可能导致程序运行变慢或崩溃。

内存溢出(Memory Overflow)是指程序试图访问超出其分配内存范围的内存位置。这通常会导致程序崩溃或不可预测的行为。

内存泄漏和内存溢出都与程序的内存管理有关,但它们发生的情境和后果是不同的。内存泄漏是指程序未能释放不再使用的内存,导致系统中的内存资源浪费。内存溢出是指程序试图访问未分配给它的内存区域,通常会导致程序崩溃

为了避免内存泄漏,我们应该负责显式释放不再使用的内存,例如使用 delete 或 free 来释放动态分配的内存。

为了避免内存溢出,要确保程序访问内存时不会超出分配的范围,例如在数组访问时要确保不越界。

3.如何判断内存泄漏?(先说一下内存泄漏的定义,再说工具)

内存泄漏是指程序在获得内存后,无法释放不使用的内存,导致系统内存不断减少的一种现象。

首先我们可以排查一下程序中每处申请内存的地方是否有与之对应的内存回收操作,另外我们还可以使用以下内存泄漏的检查工具来定位,比如Valgrind,用来统计当前申请和释放的内存是否一致,进而判断内存是否泄漏。

什么时候会发生段错误?

段错误通常发生在访问非法内存地址的时候,比如使用了野指针或者试图修改字符串常量的内容

4.c++中的内存管理(虚拟内存分布)

c++中的内存管理一般来说是用来管理虚拟内存分布的

虚拟内存分为:代码段、数据段、BSS段、堆区、文件映射区以及栈区

代码段有只读存储区和文本区,只读存储区存放字符串常量,文本区存储机器码

数据段用来保存程序中已经初始化的全局变量和静态变量

BSS(Block Started by Symbol)段用来保存未初始化的全局变量和静态变量

堆区负责在调用new/malloc时进行动态的一个内存分配

映射区则负责存储动态链接库以及调用mmap函数进行文件映射

栈使用栈空间存储函数的返回地址、参数、局部变量以及返回值

其中,代码段、数据段和bss是静态区域,堆、映射区、栈是动态区域

5.内存对齐

结构体内存对齐规则中,基本的对齐单位是字节,32位系统是4字节,64位是8字节。

然后结构体的起始地址必须是基本对齐单位的整数倍,结构体成员的偏移量必须是其类型大小或基本对齐单位的整数倍

假如有一个结构体,第一个是char,第二个是一个sizeof为1M的资源,那这个结构体有多大?

根据默认的内存对齐规则,结构体的对齐方式通常是按照结构体中最大类型的大小进行对齐。

在这种情况下,char类型的大小通常为1字节,而sizeof为1M的资源会被视为一个较大的类型,在32位系统中通常为4字节对齐,在64位系统中通常为8字节对齐。

因此,在32位系统上,这个结构体的大小将为8字节(char类型的1字节,补齐3字节,1M资源的4字节对齐);在64位系统上,这个结构体的大小将为16字节(char类型的1字节,补齐7字节,1M资源的8字节对齐)。

为什么要有内存对齐的一个操作呢?

内存对齐可以提高计算机的存取效率:

如果某个变量没有按照对齐要求存储,那么在访问该变量时,计算机可能需要进行额外的操作来调整数据的位置,从而影响系统性能。

内存对齐有助于提高缓存的命中率:

现代计算机的多级缓存通常以缓存行(cache line)为单位进行读写。如果一个结构体或数组跨越了多个缓存行,那么在访问的时候就会导致额外的缓存读取,降低缓存的效果。

因此,内存对齐可以使数据按照缓存行对齐,提高缓存命中率,提升系统性能。

还有就是一些硬件平台对于数据的对齐要求很严格,不做内存对齐可能会导致访问异常。

6.大小端

大端(Big Endian)和小端(Little Endian)是两种不同的字节序排列方式,用于存储多字节数据在计算机内存中的顺序。

大端存储是指低字节存储在高地址,小端存储是指低字节存放在低地址

对于一个只有一个字节的数字13,无论是大端还是小端存储,其表示都是相同的,因为字节的顺序在这种情况下不会有区别。不同字节序的差异通常在多字节数据类型(如整数)的存储时才会显现出来。

7.new和malloc了解吗?在分配内存时两者的区别

(答了显示指定内存以及释放内存的时候的区别)

当涉及到内存分配时,一般会使用new或malloc。

new是C++中的一个关键字,它用于在堆上动态分配内存以创建对象,并会调用构造函数进行初始化。另一方面,malloc是C语言中的一个函数,用于分配指定大小的内存块,但它不会调用构造函数。如果内存分配失败,new会抛出std::bad_alloc异常,而malloc会返回一个空指针。

总的来说,new更适合在C++中处理对象的动态分配,因为它自动处理了对象的构造,而malloc则是C语言中的标准做法。

8.堆和栈区别

栈和堆是计算机内存中用于存储数据的两个区域,它们有以下几个区别:

内存分配方式:栈采用静态内存分配(编译时分配),而堆采用动态内存分配(运行时分配)。

空间大小:栈的空间很小,通常只有几兆字节,而堆的空间很大,可以达到几百兆字节或更多。

内存管理方式:栈的管理方式由编译器自动完成,不需要程序员手动管理;而堆的管理方式由程序员手动进行内存分配和释放。

内存效率:由于栈采用静态内存分配,并且内存分配和释放都是由编译器进行管理的,所以其效率比堆要高。而堆采用动态内存分配,内存分配和释放都需要程序员手动管理,所以其效率相对较低。(栈的效率高于堆)

数据存储方式:栈中存储的数据有固定的顺序,按照先进后出的原则进行存储,而堆中的数据没有固定的顺序,可以随时进行访问。

总的来说,栈和堆各自适用于不同的场景。

栈适合存储局部变量、函数调用等数据,而堆适合存储动态分配的数据对象、大型数组等数据。在使用堆时需要注意内存泄漏和野指针等问题,需要程序员手动进行内存管理。

9.进程、线程与协程

(1)进程与线程

进程是对运行时程序的封装,是进行系统资源调度和分配的基本单位,实现了操作系统的并发。

而线程是进程的子任务,是CPU调度和分配的基本单位,用于保证程序的实时性,实现进程内部的并发

那先说一下进程。代码写好之后是一个存储在硬盘中的静态文件,编译之后会生成二进制可执行文件,当运行这个可执行文件的时候,它会被装载到内存中,接着cpu会执行程序中的每一条指令。那么这个运行中的程序就被称为进程process。

那么实际上维护多进程的开销其实是比较大的,比如进程创建、切换的时候涉及到上下文状态的保存。此外进程间通信相对来说也比较麻烦,开销也大。于是就有了线程的概念,线程是进程当中的一条执行流程,线程之间可以并发运行且内存是共享的。

线程的优点:

一个进程中可以有多个线程;

各线程之间可以并发执行;

各线程之间共享地址空间和文件等资源

线程的缺点也是由于共享内存导致的,如果某个进程内的某个线程出现问题崩溃了,那么有可能会导致该进程也跟着崩溃(因为系统可能认为后续会发生一些严重错误,所以干脆就使用信号机制kill了进程)

线程和进程的比较:

进程是资源分配的单位,线程是cpu调度的单位;

进程拥有完整的资源平台,线程只是独享必不可少的资源,比如寄存器和栈;

线程同样也具有就绪、阻塞、运行三种状态,也有状态之间相互转换的关系;

线程能够减少并发执行的时间空间开销

进程和线程的区别主要包括以下几个方面:

进程和线程的调度:操作系统将CPU时间分配给进程和线程,但是进程和线程是不同的调度单位,它们的调度方式也不同。操作系统采用多任务调度技术来进行进程的调度,而线程的调度则由进程的线程调度管理器负责。

进程和线程的内存管理:每个进程都有自己独立的地址空间,而线程共享其所属进程的地址空间。因此进程之间的内存空间是隔离的,而线程之间可以直接访问共享内存。

进程和线程间的通信:进程间通信(IPC)需要使用特殊的机制,如管道、消息队列、共享内存等;而线程间通信只需要共享同一块内存即可。

进程和线程的创建与销毁:进程需要复制父进程的地址空间,创建新的进程实体,而线程则可以通过调用库函数创建,线程的销毁也相对比较容易。

(2)协程

协程(Coroutine)是一种比线程更轻量级的并发编程方式。它可以在单个线程内实现多个协程之间的切换,从而达到并发执行的效果。

与线程不同的是,协程是由程序员显式地控制切换的,而不是由操作系统进行调度。

程序员可以定义多个协程,并在适当的时候手动切换执行。

协程的优点:

轻量级:相较于线程,协程的创建和切换开销更小,因为它们不需要操作系统的介入,而是由程序员自行控制。

高效利用CPU:协程可以通过在任务之间切换来充分利用CPU资源,减少线程切换的开销。

简化编程模型:协程可以将复杂的异步编程任务简化为顺序执行的代码,提高代码的可读性和可维护性。

避免竞态条件:由于协程在单线程中执行,不存在多线程并发访问共享数据的竞态条件问题,因此可以避免相关的线程同步和锁机制。

协程的缺点:

无法利用多核CPU:由于协程仍然运行在单个线程中,无法充分利用多核CPU的优势。

阻塞操作会阻塞整个线程:如果协程中执行了阻塞操作,如IO操作或者等待其他协程的结果,那么当前线程将被阻塞,无法处理其他协程。

总结来说,协程是一种轻量级的并发编程方式,可以在单线程内实现多个协程之间的切换,从而提高程序的并发性和效率。它通过简化编程模型和减少线程切换开销,提供了一种高效、方便的并发编程解决方案。

10.进程间通信方式

进程间通信方式有:管道、消息队列、共享内存、信号量、信号以及socket

11.线程间通信方式

主要有:互斥锁、条件变量、消息队列、共享内存等

条件变量通常与互斥锁一起使用,以确保线程在等待条件时不会出现竞争条件。在使用条件变量时,通常有两个主要操作:等待条件的线程会等待条件的发生,而其他线程会通过通知来通知等待线程。

12.阻塞和等待分别是什么?有什么区别?

答:阻塞和等待是两个与多线程和并发编程相关的概念。

阻塞是指一个线程在执行过程中因为某些原因停止了继续执行,通常是因为需要等待某个条件的满足或者资源的可用性。阻塞可以发生在多种情况下,例如等待用户输入、等待文件读写完成、等待网络数据到达等。

等待是指一个线程主动地进入等待状态,通常是因为它需要等待其他线程完成某个特定的任务或者通知。线程在等待状态下不会占用 CPU 资源,直到被唤醒。等待通常用于线程之间的协作和同步,一个线程等待另一个线程的信号或通知来继续执行。

主要区别在于阻塞是由于外部条件不满足而导致的线程暂停,而等待是线程主动选择进入等待状态,等待通常用于线程之间的协作和同步。

13.是否了解死锁?产生死锁的原因

死锁就是两个线程为了维护两个不同的共享资源而使用了两个互斥锁,如果锁使用不当就会造成两个线程都在等待对方释放资源的情况,如果没有外力介入,这种等待回一直持续下去,也就形成了死锁。

死锁要同时满足四个条件才会发生:

互斥条件;(多个线程不能同时使用一个共享资源)

持有并等待条件;(线程A在等待资源2时不会释放自己已经持有的资源1)

不可剥夺条件;(对于已经获得的共享资源,在没有用完之前其他线程不能获取)

环路等待条件;(两个线程获取资源的顺序构成了环形链)

14.进程调度

进程调度算法用于帮助CPU合理分配每个进程应该处理的任务,常见的有先来先服务调度算法、最短作业优先调度算法以及时间片轮转调度等。

先来先服务,顾名思义就是每次让就绪队列中最先入队列的进程运行,直到进程退出或阻塞。(如果长作业先运行了就会增加等待时间)

最短作业调度则是先让运行时间短的进程来运行,这样做可以提高吞吐量。(但是如果有很多短作业,长作业就会一直等着而不被执行)

时间片轮转则是权衡上述调度方法的优缺点之后的一个折中方案,即为每个进程分配时间片,这样在时间片内每个线程都可以公平的执行。

时间片设为 20ms~50ms 通常是一个比较合理的折中值

15.linux df查看文件大小,效率很快,什么原因

运行 df 命令时,操作系统通常会将文件系统的磁盘使用信息缓存到内存中。这意味着 df 不需要实际上访问磁盘上的数据,而是从内存中快速获取这些信息。此外,df 命令执行的是非常轻量级的操作,它只需要读取文件系统元数据,而不涉及读取文件的实际内容。这就会比直接读取文件要快。还有就是操作系统对df命令做了很多优化,这也是其高效的原因。

16.软连接和硬链接,是什么?删除源文件后会发生什么?

软链接是指向另一个文件的特殊文件,类似于快捷方式。它包含源文件的路径或位置信息。删除源文件后,软链接仍然存在,但指向的文件不再存在,软链接称为“悬空链接”。【ln -s命令】

硬链接是指在文件系统中创建一个源文件的副本,新创建的硬链接与源文件在磁盘上的存储位置相同。删除源文件后,硬链接仍然存在,因为它们实际上是对同一物理数据块的引用,只有当所有链接(包括源文件和硬链接)都被删除时,数据块才会被释放。【ln命令】

三.数据库

1.MySQL中效率比较低的SQL语句如何排查、优化

如果执行SQL响应比较慢,可能有以下4个原因:

第1个原因:没有索引或者没有命中导致索引失效。

针对上述情况,先收集一段时间MySQL的慢查询日志(使用SQL Profiler等工具),找出耗时最长的语句,可以利用explain去查看对应语句是否命中索引,如果没有命中,可以通过关键字来强制指定索引或者修改数据库的配置来设置查询优化器的行为。

如果没有索引,可以考虑在表上添加对应的索引

第2个原因:单表数据量数据过多,导致查询瓶颈

单表数据量过多也会出现查询瓶颈,即使使用了索引性能也不会特别好,此时就要考虑对表进行拆分,一般就是垂直拆分或者水平拆分

水平拆分的意思是把一张大表(数据行数达到千万级别的),按照业务主键切分为多张小表,这些小表可能达到100张甚至1000张。

垂直拆分的意思是,将一张单表中的多个列,按照业务逻辑把关联性比较大的列放到同一张表中去。

然后除了分表以外我们还可以考虑分库,也就是将拆分后得到的表在放到不同的数据库实例中。

这样的话,我们就可以根据业务主键把请求路由到不同数据库实例,从而让每一个数据库实例承担的流量比较小,达到提高数据库性能的目的。

第3个原因:网络原因或者机器负载过高。

这种情况可以进行读写分离

MySQL支持一主多从的分布式部署,我们可以将主库只用来处理写数据的操作,而多个从库只用来处理读操作。

在流量比较大的场景中,可以增加从库来提高数据库的负载能力,从而提升数据库的总体性能。

第4个原因:热点数据导致单点负载不均衡。

这种情况下,除了对数据库本身的策略调整以外,还可以增加缓存。

将查询比较频繁的热点数据预存到缓存当中,比如Redis、MongoDB、ES等,以此来缓解数据的压力,从而提高数据库的响应速度。

参考文章:https://www.cnblogs.com/DAYceng/p/18037696

  • 19
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI+程序员在路上

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值