写给迷糊的你看的 浏览器从输入URL到页面渲染过程(呕心泣血 1.6w字)

在这里插入图片描述

第一步:用户输入

1、 对用户所输入内容进行解析:

  • 为什么需要解析:判断出所输入的关键字是 搜索内容 还是 URL

    搜索内容:地址栏会使用浏览器默认的搜索引擎,来合成带关键字的 URL
    URL:输入内容符合 URL 规则,地址栏会根据规则,把内容加上协议,合成完整的 URL

  • 为什么要解析URL:HTTP协议中参数组件的传输是 “key=value” 键值对的形式,如果要传输多个参数就需要用“&”符号对键值对进行分隔。但是对于 value 中本就包含 =或者& 等特殊字符(例如:http:www.baidu.com?key=va&lu=e1),就会出现歧义。

    如何解决歧义:对URL进行编码(在特殊字符的各个字节(16进制)前加上”%”即可:http:www.baidu.com?key=va%26lu%3D

第二步:网络请求

1、DNS解析

DNS 的核心系统是一个三层的树状、分布式服务,基本对应域名的结构:

根域名服务器(Root DNS Server):管理顶级域名服务器,返回“com”“net”“cn”等顶级域名服务器的 IP 地址。
顶级域名服务器(Top-level DNS Server):管理各自域名下的权威域名服务器,比如 com 顶级域名服务器可以返回 apple.com 域名服务器的 IP 地址。
权威域名服务器(Authoritative DNS Server):管理自己域名下主机的 IP 地址,比如 apple.com 权威域名服务器可以返回 www.apple.com 的 IP 地址。
在这里插入图片描述
解析流程:

在这里插入图片描述

1、在浏览器中输入www.qq.com域名,操作系统会先检查自己本地的hosts文件是否有这个网址映射关系,如果有,就先调用这个IP地址映射,完成域名解析。

2、如果hosts里没有这个域名的映射,则查找本地DNS解析器缓存,是否有这个网址映射关系,如果有,直接返回,完成域名解析。

3、如果hosts与本地DNS解析器缓存都没有相应的网址映射关系,首先会找TCP/IP参数中设置的首选DNS服务器,在此我们叫它本地DNS服务器,此服务器收到查询时,如果要查询的域名,包含在本地配置区域资源中,则返回解析结果给客户机,完成域名解析,此解析具有权威性。

4、如果要查询的域名,不由本地DNS服务器区域解析,但该服务器已缓存了此网址映射关系,则调用这个IP地址映射,完成域名解析,此解析不具有权威性。

5、如果本地DNS服务器本地区域文件与缓存解析都失效,则根据本地DNS服务器的设置(是否设置转发器)进行查询,如果未用转发模式,本地DNS就把请求发至13台根DNS,根DNS服务器收到请求后会判断这个域名(.com)是谁来授权管理,并会返回一个负责该顶级域名服务器的一个IP。本地DNS服务器收到IP信息后,将会联系负责.com域的这台服务器。这台负责.com域的服务器收到请求后,如果自己无法解析,它就会找一个管理.com域的下一级DNS服务器地址(qq.com)给本地DNS服务器。当本地DNS服务器收到这个地址后,就会找qq.com域服务器,重复上面的动作,进行查询,直至找到www.qq.com主机。

6、如果用的是转发模式,此DNS服务器就会把请求转发至上一级DNS服务器,由上一级服务器进行解析,上一级服务器如果不能解析,或找根DNS或把转请求转至上上级,以此循环。不管是本地DNS服务器用是是转发,还是根提示,最后都是把结果返回给本地DNS服务器,由此DNS服务器再返回给客户机。

2、建立TCP链接

在OSI 模型中共有七层,从下到上分别是物理层、数据链路层、网络层、运输层、会话层、表示层和应用层。但是这显然是有些复杂的,所以在 TCP/IP 协议中,它们被简化为了四层。
在这里插入图片描述
当然,TCP/IP 是协议族的统称,在OSI七层模型中:
在这里插入图片描述
三次握手

很多人都看过三次握手四次挥手的流程图,但是总是不明白、记不住。最主要的原因还是我们对其含义不理解:
在这里插入图片描述

流程图:
在这里插入图片描述

  1. 初始时,客户端处于 Colse(关闭) 状态,服务端处于 Listen(监听) 状态。
  2. 客户端想要和客户端建立连接。
  3. 第一次握手:客户端 发送 SYN=1(初始化建立连接),seq=x 给服务端,消息发完后此时 客户端处于SYN_SENT 状态,等待服务器的确认。
  4. 第二次握手:服务端收到客户端发送的想要建立连接的信息,会发送ACK=1 表明确认收到消息,并以自己的 SYN=1 报文作为应答,表示可以建立连接,并且也是指定了自己的初始化序列号 seq=y,同时会把客户端的 seq + 1 作为ack 的值(ack=x+1),表示自己已经收到了客户端的 SYN,此时服务器处于 SYN_REVD 的状态。
  5. 第三次握手:客户端收到服务端可以建立链接的信息,于是发送 ACK=1 表明确认收到消息, 并且指定序列号seq=x+1(初始为seq=x,第二个报文段所以要+1),同时会把服务端的 seq + 1 作为ack(ack=y+1) 的值,表示自己已经收到了客户端的 SYN,消息发送后,此时 客户端处于 ESTABLISHED(已确认) 状态,服务端接收到此消息后,也变为 ESTABLISHED(已确认) 状态。

为什么需要三次握手,两次不行吗?

三次握手、四次挥手 的目的就是为了确认双方是否可接受可发送数据。如果改为两次握手,假如客户端第一次发送了建立连接的消息(第一次握手),由于网络卡顿了或其他原因,没有及时传达到服务端,过了一会儿时间,客户端迟迟未收到服务端的确认消息,便取消了这次信息传输,但是一段时间后,服务端终于接收到了此条消息,于是向客户端发送可建立连接的消息(第二次握手),如果只有两次握手,那么此时双方的连接就建立了,此时客户端忽略服务端发来的确认,也不发送数据,则服务端一直等待客户端发送数据,浪费资源。
在这里插入图片描述

第三次握手失败了怎么办?

当客户端与服务端的第三次握手失败了之后,即客户端发送至服务端的确认建立连接报文段未能到达服务端,服务端发送了SYN+ACK报文后就会启动一个重传计时器,等待客户端返回的ACK报文,如果服务端在等待客户端回复ACK的过程中超过规定时间后重新发送SYN+ACK,重传次数根据 /proc/sys/net/ipv4/tcp_synack_retries 来指定,默认是5次。如果重传指定次数到了后,仍然未收到ACK应答,那么一段时间后,server自动关闭这个连接,那么服务端会向客户端发送一个RTS报文段并进入CLOSE关闭状态,即:并不等待客户端第三次握手的ACK包重传,直接关闭连接请求,这主要是为了防止泛洪(SYN)攻击,即坏人伪造许多IP向服务端发送连接请求,从而将服务端的未连接队列塞满,浪费服务端的资源。
在这里插入图片描述

3、发送HTTP请求

提到HTTP,我们最先想到的就是HTTP与HTTPS:

HTTP:超文本传输协议(Hypertext Transfer Protocol)。
HTTPS:超文本传输安全协议(Hypertext Transfer Protocol Secure),其实就是在HTTP的基础上加上了TLS/SSL协议。

为什么会有HTTPS?

为什么会有HTTPS,其实就是在问HTTP与HTTPS的区别,首先我们来了解一下HTTP的结构:

请求:
在这里插入图片描述
响应:
在这里插入图片描述
HTTP与HTTPS的主要区别:
在这里插入图片描述

4、四次挥手

在这里插入图片描述

  1. 初始时,客户端和服务端都处于ESTABLISHED(已建立连接状态)。
  2. 有一方想要发起关闭连接请求(假设为客户端),客户端首先发出 FIN=1, 序列号 seq=u 的结束信号消息,此时 客户端变为 FIN_WAIT1 状态。
  3. 服务端收到消息后,首先回复 ACK=1, ack=u+1, seq=v 表明收到上一条想要结束连接的消息,此时服务端变为 CLOSE_WAIT 状态,接下来服务端会去检查是否可以结束连接(没有需要再传输的请求或数据)。
  4. 客户端收到上一条消息后,变为 FIN_WAIT2 状态,继续等待服务端可以结束连接的消息传来。
  5. 服务端确定可以断开连接后,会再向 客户端发送 FIN=1(结束标志), ACK =1,ack = u+1, seq = w 的消息表明可以结束连接的消息,此时服务端变为 LAST_ACK(最后一次发送消息)状态,等待 客户端的 确认。
  6. 客户端收到FIN消息后,回复 ACK=1,ack=w+1,seq=u+1表明收到上一条可以结束的消息,此时客户端变为 TIME_WAIT状态,并设置时间等待定时器时间 为2MSL,这么做的原因是确保消息被服务器接收到,定时器时间到后,客户端才会变为CLOSED状态(客户端(发起结束信号的一方)主动变为CLOSED状态)。
  7. 服务端收到上一条消息后,状态变为 CLOSED(客户端(接收结束信号的一方)是被动变为CLOSED)。

为什么需要四次挥手才能结束连接?

如果接收结束消息的一方 收到FIN=1,seq=u 这条想要结束连接的消息后,就直接回复FIN=1(结束标志), ACK =1,ack = u+1, seq = w 消息,确定可以结束连接,最终连接被关闭,双方变为CLOSE状态,那么如果在收到第一条想要结束的消息时,还有将要传输或者正在进行的消息传输就会被被迫终止,所以必须在这之前先回复一条收到消息的报文,在对自身是否可以断开连接进行检查,确保已没有需要传输信息后,再回复FIN来结束连接。

四次挥手释放连接时,等待2MSL的意义是什么?

MSL(最长报文段寿命):报文在网络上存活的最长时间,超过这个时间报文将会被丢弃。
意义一:确保客户端(主动结束方发送)的最后一条消息不被丢失。如果最后一条消息被丢失了,服务端没有收到这条消息,因为服务端在发出SYN+ACK这条消息后,会设置一个重传定时器,在规定的时间内没有收到来自客户端的确认,会重传第三条消息,再次设置定时器,假设客户端不等待2MSL,而是在发送完ACK之后直接释放关闭,一但这个ACK丢失的话,服务器就无法正常的进入关闭连接状态。
意义二:防止“已失效的连接请求报文段”出现在本连接中。客户端(主动结束方发送)在发送完最后一个ACK报文段后,再经过2MSL,就可以使本连接持续的时间内所产生的所有报文段都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文段。

5、浏览器缓存

当我们在地址栏输入URL后,进行回车,是否就每次都会执行相关的查询操作呢?
不是

下面这张图很好的展示了浏览器缓存的运作流程:
在这里插入图片描述

当我们发起GET请求,请求还未发出时,浏览器会首先检查 是否有缓存 ,如果 存在缓存 ,是否为强缓存,强缓存不需要发送请求到服务器,直接取浏览器本地缓存即可,如果不存在强缓存或者强缓存失效,则走协商缓存。

1、如何检查是否存在强缓存?

强缓存由 Expires、Cache-Control 和 Pragma(优先级依次递增) 3 个 Header 属性共同来控制

Expires: Expires是在HTTP/1.0时期提出的,它的值是一个 HTTP 日期,在浏览器发起请求时,会根据系统时间和 Expires 的值进行比较,如果系统时间超过了 Expires 的值,缓存失效。它的缺陷也很明显:由于和系统时间进行比较,所以当系统时间和服务器时间不一致的时候,会有缓存有效期不准的问题。(优先级最低)

Cache-Control: Cache-Control 是 HTTP/1.1 中新增的属性。(优先级中等)常用的属性值如有:
max-age:单位是秒,缓存时间计算的方式是距离发起的时间的秒数,超过间隔的秒数缓存失效
no-cache:不使用强缓存,需要与服务器验证缓存是否新鲜
no-store:禁止使用缓存(包括协商缓存),每次都向服务器请求最新的资源
private:专用于个人的缓存,中间代理、CDN 等不能缓存此响应
public:响应可以被中间代理、CDN 等缓存
must-revalidate:在缓存过期前可以使用,过期后必须向服务器验证

Pragma: Pragma 只有一个属性值,就是 no-cache ,效果和 Cache-Control 中的 no-cache 一致,不使用强缓存,需要与服务器验证缓存是否新鲜。(优先级最高)

2、协商缓存

协商缓存分为两种:ETag/If-None-MatchLast-Modified/If-Modified-Since

ETag/If-None-Match:

ETag 是服务器根据当前文件的内容,给文件生成的唯一标识,只要里面的内容有改动,这个值就会变。服务器通过响应头把这个值给浏览器。 浏览器接收到 ETag 的值,会在下次请求时,将这个值作为 If-None-Match 这个字段的内容,并放到请求头中,然后发给服务器。 服务器接收到 If-None-Match 后,会跟服务器上该资源的 ETag 进行比对:

  • 如果两者不一样,说明要更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。

  • 否则返回304,告诉浏览器直接用本地缓存。

Last-Modified/If-Modified-Since:

在浏览器第一次给服务器发送请求后,服务器会在响应头中加上 Last-Modified(最后修改时间) 这个字段。浏览器接收到后,会在下次请求时,将这个值作为 If-Modified-Since 这个字段的内容,并放到请求头中,然后发给服务器。服务器拿到请求头中的 If-Modified-Since 的字段后,其实会和这个服务器中该资源的最后修改时间对比:

  • 如果请求头中的这个值小于最后修改时间,说明是时候更新了。返回新的资源,跟常规的HTTP请求响应的流程一样。

  • 否则返回304,告诉浏览器直接用本地缓存。

两者的区别:

在精准度上,ETag优于Last-Modified。优于 ETag 是按照内容给资源上标识,因此能准确感知资源的变化。而 Last-Modified 就不一样了,它在一些特殊的情况并不能准确感知资源变化,主要有两种情况:

  • 编辑了资源文件,但是文件内容并没有更改,这样也会造成缓存失效。Last-Modified 能够感知的单位时间是秒,如果文件在 1 秒内改变了多次,那么这时候的 Last-Modified 并没有体现出修改了。

  • 在性能上,Last-Modified 优于 ETag,因为 Last-Modified 仅仅只是记录一个时间点,而 Etag 需要根据文件的具体内容生成哈希值。

  • 如果两种方式都支持的话,服务器会优先考虑ETag。

3、都说使用 浏览器本地缓存 ,那么 浏览器的本地缓存 到底存在哪里呢?

浏览器的缓存位置一共有四种:Service Worker、Memory Cache(内存缓存)、Disk Cache(硬盘缓存)、Push Cache(推送缓存)(优先级从高到低)

它们的执行流程为:
在这里插入图片描述
Service Worker:

Service worker是一个注册在指定源和路径下的事件驱动worker。它采用JavaScript控制关联的页面或者网站,拦截并修改访问和资源请求,细粒度地缓存资源。它的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。这个缓存是永久性的,即关闭 TAB 或者浏览器,下次打开依然还在(而 memory cache 不是)。有两种情况会导致这个缓存中的资源被清除:手动调用 API cache.delete(resource) 或者容量超过限制,被浏览器全部清空。

Service worker运行在worker上下文,因此它不能访问DOM。相对于驱动应用的主JavaScript线程,它运行在其他线程中,所以不会造成阻塞。它设计为完全异步,同步API(如XHR和localStorage)不能在service worker中使用。

出于安全考量,Service workers只能由HTTPS承载,毕竟修改网络请求的能力暴露给中间人攻击会非常危险。在Firefox浏览器的用户隐私模式,Service Worker不可用。

Memory Cache:

Memory Cache 即内存中的缓存。几乎所有的网络请求资源都会被浏览器自动加入到 memory cache 中。按照操作系统的常理:先读内存,再读硬盘,所以从效率上讲它是最快的。但是也正因为数量很大但是浏览器占用的内存不能无限扩大这样两个因素,memory cache 注定只能是个“短期存储”。常规情况下,浏览器的 TAB 关闭后该次浏览的 memory cache 便告失效 (为了给其他 TAB 腾出位置)。而如果极端情况下 (例如一个页面的缓存就占用了超级多的内存),那可能在 TAB 没关闭之前,排在前面的缓存就已经失效了。

Disk Cache:

Disk Cache 即存储在硬盘上的缓存,因此它是持久存储的,是实际存在于文件系统中的,从存取效率上讲是比内存缓存慢的,但是他的优势在于存储容量和存储时长。而且它允许相同的资源在跨会话,甚至跨站点的情况下使用,例如两个站点都使用了同一张图片,Disk Cache 会严格根据 HTTP 头信息中的各类字段来判定哪些资源可以缓存,哪些资源不可以缓存;哪些资源是仍然可用的,哪些资源是过时需要重新请求的。当命中缓存之后,浏览器会从硬盘中读取资源,虽然比起从内存中读取慢了一些,但比起网络请求还是快了不少的。

Push Cache:

Push Cache是 HTTP/2 中的内容,当以上三种缓存都没有命中时,它才会被使用。它只在会话(Session)中存在,一旦会话结束就被释放,并且缓存时间也很短暂,在Chrome浏览器中只有5分钟左右,同时它也并非严格执行HTTP头中的缓存指令。

第三步:页面渲染

1、构建布局树(render tree)

构建DOM树:

当我们请求完成之后,如果响应头里的 Content-Typetext/html,那就意味着浏览器需要进行解析和渲染工作了。

了解React,Vue等框架的同学应该都会知道Virtual DOM(虚拟DOM),diff算法 的第一步就是将 HTML 转化为可维护的 DOM树,浏览器也一样。浏览器无法直接识别我们的 HTML 内容,需要把它转化成为浏览器可识别的文件结构–DOM树。

HTML文件内容就是一个个的DOM节点,DOM节点有它所对应的父子节点,class,style等属性。
DOM树本质上是一个以document为根节点的多叉树。

如何将HTML文件解析成DOM树?

1、标签解析

这部分完成从HTML字符串中解析出标签的功能。主要使用标记化算法。

标记化算法的输入结果是HTML标记,使用状态机表示。状态机一共有4个状态:数据状态(Data)、标记打开状态(Tag open)、标记名称状态(Tag name)、关闭标记打开状态(Close tag open state)

初始状态是 数据状态。

当标记是处于数据状态时:
1)遇到字符 < 时,状态更改为 “标记打开状态”
a. 接收一个 a-z 字符会创建 “起始标记” ,状态更改为 “标记名称状态” ,并保持到接收 > 字符。此期间的字符串会形成一个新的标记名称。接收到 > 标记后,将当前的 新标记 发送给 树构造器 ,状态改回 “数据状态”
b. 接收下一个输入字符 / 时,会创建 关闭标记打开状态 ,并更改为 “标记名称状态” 。直到接收 > 字符,将当前的 新标 记发送给 树构造器,并改回 “数据状态”
2)遇到 a-z字符时,会将每个字符创建成字符标记,并发送给树构造器。

注意⚠️:

如果我们在解析的过程中遇到 “< script ></ script >“标签,当前线程会被停止,去加载 js 文件,因为 js文件可能会涉及到 DOM节点或者CSS样式 的更改,这是它无法预测的,当 js 文件加载结束后,该线程会继续执行下去。这就是为什么我们建议把 js文件 放在body的最后,因为 JS 会阻塞 DOM 树的解析。

那为什么又会建议把 CSS文件 放在前面加载呢?

CSS解析 和 DOM解析 是在不同的线程中执行的,但是绘制 Render Tree(后面会提到) 必须要 CSS解析 和 DOM解析 都完成后才可以进行的,CSS解析 并不会影响 DOM解析,但它会阻塞 DOM渲染,所以我们建议把 CSS文件 放在前面加载。

2、DOM树构建

当标签解析器解析出标签后会发送到DOM树构建器,DOM树构建器主要有这两部分组成:DOM树、一个存放标签名的栈

我们举个例子说明:

<html>
	<body>
	    <h1 style="color: red"></h1>
	    <div>
	            <p style="display: none"></p>
	    </div>
	</body>
</html>

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
2、CSS树构建

css来源有三种:外部样式表、内部样式表、内联样式,因此,在生成css tree时,会根据各个样式表,通过 继承、层叠 来计算出最终样式。

与处理 HTML 时一样,我们需要将收到的 CSS 规则转换成某种浏览器能够理解和处理的东西。因此,我们会重复 HTML 过程,不过是为 CSS 而不是 HTML:
在这里插入图片描述
3、合成 render tree
在这里插入图片描述
通过上图我们可以清楚的发现:render tree 只会保留可见元素。

2、构建图层树

1、建立图层树(layer tree)

现在,虽然我们已经有了 render tree 和 css tree,但是我们也无法保证能够正确渲染出页面,因为还会有一些复杂的场景,比如3D动画如何呈现出变换效果,当元素含有层叠上下文时(定位,z-index等)如何控制显示和隐藏等等。所以,还需 图层树(layer tree)来解决问题。

一般情况下,节点的图层会默认属于父亲节点的图层(这些图层也称为合成层)。那什么时候会提升为一个单独的合成层呢?

有两种情况需要分别讨论,一种是显式合成,一种是隐式合成

显式合成:

  • 拥有层叠上下文的节点

    HTML根元素本身就具有层叠上下文
    普通元素设置position不为static并且设置了z-index属性,会产生层叠上下文
    元素的 opacity 值不是 1
    元素的 transform 值不是 none
    元素的 filter 值不是 none
    元素的 isolation 值是isolate
    will-change指定的属性值为上面任意一个

  • 需要剪裁的地方:

    比如一个div,你只给他设置 100 * 100 像素的大小,而你在里面放了非常多的文字,那么超出的文字部分就需要被剪裁。当然如果出现了滚动条,那么滚动条会被单独提升为一个图层。

隐式合成:

层叠等级低的节点被提升为单独的图层之后,那么所有层叠等级比它高的节点都会成为一个单独的图层,这个隐式合成其实隐藏着巨大的风险,如果在一个大型应用中,当一个z-index比较低的元素被提升为单独图层之后,层叠在它上面的的元素统统都会被提升为单独的图层,可能会增加上千个图层,大大增加内存的压力,甚至直接让页面崩溃,这就是层爆炸的原理。

这时,我们就不得不来聊一聊 重排(回流)重绘 了:

重排(回流):当DOM的变化引发了元素几何属性的变化,比如改变元素的宽高,元素的位置,导致浏览器不得不重新计算元素的几何属性,并重新构建渲染树,这个过程称为“重排”。

常见的引起重排的操作:

  • 一个 DOM 元素的几何属性变化,常见的几何属性有width、height、padding、margin、left、top、border 等等, 这个很好理解。
  • 使 DOM 节点发生增减或者移动。
  • 读写 offset族、scroll族和client族属性的时候,浏览器为了获取这些值,需要进行回流操作。
  • 调用 window.getComputedStyle 方法。
    在这里插入图片描述

重绘: 完成重排后,要将重新构建的渲染树渲染到屏幕上,这个过程就是“重绘”。重绘不一定引起重排,但重排一定伴有重绘。

让我们先来回顾一下

2、生成绘制列表

接下来渲染引擎会将图层的绘制拆分成一个个绘制指令,比如先画背景、再描绘边框…然后将这些指令按顺序组合成一个待绘制列表,相当于给后面的绘制操作做了一波计划。

通过Chrome 开发者工具中 more tools的Layers面板可以观察到:
在这里插入图片描述
3、生成图块和生成位图

绘制列表准备好了之后,渲染进程的主线程会给合成线程发送commit消息,把绘制列表提交给合成线程。

但是我们的视口大小有限,但是我们的页面非常大,需要滑动很长时间才能滑到底,如果一次性把全部绘制出来是非常浪费性能的。因此,合成线程要做的第一件事情就是将图层按照分块,然后根据可视区上下的的图库转化成位图,这一步也叫栅格化,这样可以提高页面的首屏展示效率。

4、合成与显示

栅格化完成后,合成线程会生成一个"DrawQuad"的命令,并发送给浏览器进程,浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。

写在最后:

参考博文:
DNS原理及其解析过程:https://blog.51cto.com/369369/812889
一文读懂前端缓存:https://juejin.cn/post/6844903747357769742

  • 4
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
MySQL是一种关系型数据库管理系统,被广泛应用于各类网站、应用程序和企业级系统中。它是由瑞典MySQL AB公司开发的,后来被Sun Microsystems收购,最终成为了Oracle公司的一部分。 MySQL以其高性能、稳定性和可靠性而闻名,不仅能够处理大规模的数据处理需求,还具备较高的扩展性和可定制性。它支持多用户访问和并发操作,并提供了完善的安全性和权限管理机制,可灵活控制用户对数据的访问权限。 MySQL采用了客户端-服务器架构,其中客户端可以是各种编程语言实现的应用程序,而服务器则负责存储和处理数据。MySQL使用了一种基于SQL(Structured Query Language,结构化查询语言)的查询语言,通过执行SQL语句实现数据的存储、检索和管理。 MySQL支持多种存储引擎,如InnoDB、MyISAM、MEMORY等,每个存储引擎都有其特定的优势和适用场景。同时,MySQL还支持事务处理和数据备份恢复等常用功能,保证了数据的完整性和可靠性。 MySQL拥有庞大的用户群体和强大的社区支持,用户可以通过官方文档、在线论坛和社交媒体等渠道获取帮助和交流经验。此外,MySQL还有丰富的第三方工具和插件生态系统,可提供更多功能和扩展性。 总之,MySQL作为一种成熟、可靠的关系型数据库管理系统,被广泛应用于各类场景。它的强大功能、高性能和可扩展性使其成为了开发者们首选的数据库解决方案之一。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值