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

【MySQL 系列】MySQL 架构篇

在我们开始了解 MySQL 核心功能之前,首先我们需要站在一个全局的视角,来看 SQL 是如何运作执行的。通过这种方式,我们可以在头脑中构建出一幅 MySQL 各组件之间的协同工作方式,有助于我们加深对 MySQL 服务器的理解。


文章目录

        • 1、MySQL 的逻辑架构
        • 2、SELECT 语句执行原理
          • 2.1、连接器
          • 2.2、连接池
          • 2.3、查询缓存
          • 2.4、解析 SQL
          • 2.5、执行 SQL
          • 2.6、SELECT 查询过程
        • 3、UPDATE 语句执行原理
          • 3.1、缓冲池
          • 3.2、InnoDB 内存结构和磁盘结构
            • 3.2.1、BufferPool
            • 3.2.2、ChangeBuffer
            • 3.2.3、Log Buffer
          • 3.3、UPDATE 更新过程


1、MySQL 的逻辑架构

MySQL 的架构共分为两层:Server 层和存储引擎层

Server 层:负责建立连接、分析和执行 SQL。MySQL 大多数的核心功能模块都在这实现,主要包括连接池,执行器、优化器、解析器、预处理器、查询缓存等。另外,所有的内置函数(如日期、时间、数学和加密函数等)和所有跨存储引擎的功能(如存储过程、触发器、视图等)都在 Server 层实现;

存储引擎层:负责数据的存储和提取。支持 InnoDB、MyISAM、Memory 等多个存储引擎,不同的存储引擎共用一个 Server 层。现在最常用的存储引擎是 InnoDB,从 MySQL 5.5 版本开始, InnoDB 成为了 MySQL 的默认存储引擎。我们常说的索引数据结构,就是由存储引擎层实现的。

image-20240307102437700


2、SELECT 语句执行原理
2.1、连接器

当我们通过客户端访问 MySQL 服务器前,要做的第一步就是需要先经过 TCP 三次握手,因为 MySQL 是基于 TCP 协议进行传输的

连接的过程需要先经过 TCP 三次握手,因为 MySQL 是基于 TCP 协议进行传输的。

TCP 网络连接建立成功后,服务端与客户端之间会建立一个 session 会话,紧接着会对登录的用户名和密码进行效验,首先会查询自身的用户表信息,判断输入的用户名是否存在,如果存在则会判断输入的密码是否正确。密码正确后,会从连接池中分配一条空闲线程维护当前客户端的连接;如果没有空闲线程,则会创建一条新的工作线程。之后线程会查询用户所拥有的权限,并对其授权,后续 SQL 执行时,都会先判断是否具备相应的权限。

空闲连接在超过最大空闲时长(wait_timeout)之后,连接器会自动将它断开。

一个处于空闲状态的连接被服务端主动断开后,客户端并不会马上知道,等到客户端在发起下一个请求的时候,才会收到报错。

image-20240307214513557

2.2、连接池

Connection Pool,是程序启动时建立足够的数据库连接,并将这些连接组成一个连接池,由程序动态地对池中的连接进行申请、使用、释放。主要是为了复用线程、管理线程以及限制最大连接数。

当一个客户端尝试与 MySQL 建立连接时,MySQL 内部都会派发一条线程负责处理该客户端接下来的所有工作。

线程的频繁创建和销毁都会耗费大量资源,通过复用线程的方式,不仅能减少开销,还能避免内存溢出等问题。

数据库连接池可以设置最小连接数和最大连接数:

  • 最小连接数:是连接池一直保持的数据库连接,如果应用程序对数据库连接的使用量不大,将会有大量的数据库连接资源被浪费;
  • 最大连接数:是连接池能申请的最大连接数,如果数据库连接请求超过次数,后面的数据库连接请求将被加入到等待队列中。
2.3、查询缓存

如果查询语句(select 语句),MySQL 就会先去查询缓存( Query Cache )里查找缓存数据,看看之前有没有执行过这一条命令,这个查询缓存是以 key-value 形式保存在内存中的,key 为 SQL 查询语句的哈希值,value 为 SQL 语句查询的结果。

如果查询的语句命中查询缓存,那么就会直接返回 value 给客户端。如果查询的语句没有命中查询缓存中,那么就要往下继续执行,等执行完后,查询的结果就会被存入查询缓存中。

查询缓存往往弊大于利,因为只要有对表的更新,就会导致表上的所有查询缓存被清空。所以,MySQL8.0 版本直接将查询缓存删掉了。

这里说的查询缓存是 server 层的,也就是 MySQL8.0 版本移除的是 server 层的查询缓存,并不是 Innodb 存储引擎中的 buffer poll。

2.4、解析 SQL

在正式执行 SQL 查询语句之前, MySQL 会先对 SQL 语句做解析,这个工作交由解析器来完成。解析器可以将输入的 SQL 语句转换为计算机可以理解的形式(语法树,Syntax Tree)。

解析器会做如下两件事情:

  • 词法解析:MySQL 会根据输入的字符串识别出关键字出来,构建出 SQL 语法树;
  • 语法解析:根据词法分析的结果,语法分析器会根据语法规则,判断输入的 SQL 语句是否满足语法规则。

语法树大致结构如下:

image-20240307110242224

当词法分析和语法分析出错时,分析器会抛出异常。比如语法结构出错、出现了无法识别的字符等。

表或者字段不存在,并不是在分析器里做的,而是在预处理阶段完成。

2.5、执行 SQL

每条 SQL 语句主要可以分为以下这三个阶段:① prepare ,预处理阶段;② optimize ,优化阶段;③ execute ,执行阶段。

预处理器:检查 SQL 查询语句中的表或者字段是否存在;将 select * 中的 * 符号,扩展为表上的所有字段;

优化器:化器会根据语法树制定多个执行计划,然后确定最优的执行计划。

  • 在表里存在多个索引的时候,决定使用哪个索引;
  • 在一个语句有多表关联(join)的时候,决定各个表的连接顺序。

执行器:判断用户权限,然后根据执行计划执行 SQL 语句。

2.6、SELECT 查询过程

总结一下一条查询 SQL 语句的执行流程:

  1. 客户端通过连接器连接 MySQL 服务;
  2. 连接成功后向 SQL 接口发送 SQL 语句请求;
  3. SQL 接口接收到 SQL 查询语句会先去缓存查询,如果命中返回给客户端,否则交给解析器;
  4. 解析器在拿到 SQL 语句后会判断语法是否正确,正确会生成 SQL 语法树交给优化器,否则报错给客户端;
  5. 优化器会根据 SQL 语法树生成一个最优的执行计划交给执行器执行;
  6. 执行器拿到执行计划调用存储引擎来获取数据响应给客户端;
  7. 完成!!!

3、UPDATE 语句执行原理

在数据库里面,我们说的 update 操作其实包括了更新、插入和删除。如果大家有看过 MyBatis 的源码,应该知道 Executor 里面也只有 doQuery()doUpdate() 的方法,没有 doDelete()doInsert()

3.1、缓冲池

首先,InnnoDB 的数据都是放在磁盘上的,InnoDB 操作数据有一个最小的逻辑单位,叫做页(索引页和数据页)。我们对于数据的操作,不是每次都直接操作磁盘,因为磁盘的速度太慢了。InnoDB 使用了一种缓冲池的技术,也就是把磁盘读到的页放到一块内存区域里面。这个内存区域就叫 Buffer Pool.

下一次读取相同的页,先判断是不是在缓冲池里面,如果是,就直接读取,不用再次访问磁盘。

修改数据的时候,先修改缓冲池里面的页。内存的数据页和磁盘数据不一致的时候,我们把它叫做脏页。InnoDB 里面有专门的后台线程把 BufferPool 的数据写入到磁盘,每隔一段时间就一次性地把多个修改写入磁盘,这个动作就叫做刷脏。

BufferPool 是 InnoDB 里面非常重要的一个结构,它的内部又分成几块区域。这里我们趁机到官网来认识一下 InnoDB 的内存结构和磁盘结构。

3.2、InnoDB 内存结构和磁盘结构

BufferPool 主要分为3个部分:Buffer Pool、Change Buffer、AdaptiveHash Index,另外还有一个(redo)logbuffer。

image-20240307215513236

3.2.1、BufferPool

BufferPool 缓存的是页面信息,包括数据页、索引页。查看服务器状态,里面有很多跟 BufferPool 相关的信息:

SHOW STATUS LIKE '%innodb_buffer_pool%';

image-20240307215749647

这些状态都可以在官网查到详细的含义,用搜索功能。

BufferPool 默认大小是 128M(134217728字节),可以调整。查看参数(系统变量):

SHOW VARIABLES like' %innodb_buffer_pool%';

这些参数都可以在官网查到详细的含义,用搜索功能。

内存的缓冲池写满了怎么办?InnoDB 用 LRU 算法来管理缓冲池(链表实现,不是传统的 LRU,分成了Younf 和 Old),经过淘汰的数据就是热点数据。

内存缓冲区对于提升读写性能有很大的作用。思考一个问题:当需要更新一个数据页时,如果数据页在 BufferPool 中存在,那么就直接更新好了。否则的话就需要从磁盘加载到内存,再对内存的数据页进行操作。也就是说,如果没有命中缓冲池,至少要产生一次磁盘 IO,有没有优化的方式呢?

3.2.2、ChangeBuffer

如果这个数据页不是唯一索引,不存在数据重复的情况,也就不需要从磁盘加载索引页判断数据是不是重复(唯一性检查)。这种情况下可以先把修改记录在内存的缓冲池中,从而提升更新语句(Insert、Delete、Update)的执行速度。

这一块区域就是 ChangeBuffer。5.5 之前叫 InsertBuffer 插入缓冲,现在也能支持 Delete 和 Update。

最后把 ChangeBuffer 记录到数据页的操作叫做 merge。什么时候发生 merge?有几种情况:在访问这个数据页的时候,或者通过后台线程、或者数据库 shutdown、redolog 写满时触发。

如果数据库大部分索引都是非唯一索引,并且业务是写多读少,不会在写数据后立刻读取,就可以使用 ChangeBuffer(写缓冲)。写多读少的业务,调大这个值:

SHOW VARIABLES LIKE 'innodb_change_buffer_max_size';

代表 ChangeBuffer 占 BufferPool 的比例,默认 25%。

3.2.3、Log Buffer

思考一个问题:如果 BufferPool 里面的脏页还没有刷入磁盘时,数据库宕机或者重启,这些数据丢失。如果写操作写到一半,甚至可能会破坏数据文件导致数据库不可用。

为了避免这个问题,InnoDB 把所有对页面的修改操作专门写入一个日志文件,并且在数据库启动时从这个文件进行恢复操作(实现 crash-safe)——用它来实现事务的持久性。

image-20240307222539054

这个文件就是磁盘的 Redo Log(叫做重做日志),对应于 /var/lib/mysql/ 目录下的 ib_logfile0ib_logfile1,每个 48M。

这种日志和磁盘配合的整个过程 ,其实就是 MySQL 里的 WAL 技术(Write-Ahead Logging),它的关键点就是先写日志,再写磁盘。

show variables like 'innodb_log%';

image-20240307221523233

问题:同样是写磁盘,为什么不直接写到 db file 里面去?为什么先写日志再写磁盘?

我们先来了解一下随机 I/O 和顺序 I/O 的概念:磁盘的最小组成单元是扇区,通常是 512 个字节。操作系统和磁盘打交道,读写磁盘,最小的单位是块 Block。

image-20240307224606072

如果我们所需要的数据是随机分散在不同页的不同扇区中,那么找到相应的数据需要等到磁臂旋转到指定的页,然后盘片寻找到对应的扇区,才能找到我们所需要的一块数据,依次进行此过程直到找完所有数据,这个就是随机 IO,读取数据速度较慢。

假设我们已经找到了第一块数据,并且其他所需的数据就在这一块数据后边,那么就不需要重新寻址,可以依次拿到我们所需的数据,这个就叫顺序 IO。

刷盘(将内存中的数据写入磁盘)是随机 I/O,而记录日志是顺序 I/O,顺序 I/O 效率更高。因此先把修改写入日志,可以延迟刷盘时机,进而提升系统吞吐。

当然 Redo Log 也不是每一次都直接写入磁盘,在 Buffer Pool 里面有一块内存区域(Log Buffer)专门用来保存即将要写入日志文件的数据,认 16M,它一样可以节省磁盘 IO.

image-20240307222502459

需要注意:Redo Log 的内容主要是用于崩溃恢复。磁盘的数据文件,数据来自 bufferpool。Redo Log 写入磁盘,不是写入数据文件。那么,Log Buffer 什么时候写入 log file?在我们写入数据到磁盘的时候,操作系统本身是有缓存的。flush 就是把操作系统缓冲区写入到磁盘。

Redo Log 的特点:

  1. Redo Log 是 InnoDB 存储引擎实现的,并不是所有存储引擎都有;
  2. 不是记录数据页更新之后的状态,而是记录这个页做了什么改动,属于物理日志;
  3. Redo Log 的大小是固定的,前面的内容会被覆盖。

除了 Redo Log之外,还有一个跟修改有关的日志,叫做 Undo Log(撤销日志或回滚日志),记录了事务发生之前的数据状态,分为 insert Undo Log 和 update Undo Log。如果修改数据时出现异常,可以用 Undo Log 来实现回滚操作(保持原子性)。

3.3、UPDATE 更新过程

有了 Redo Log 和 Undo Log,我们来总结一下一个 Update 操作的流程。

UPDATE user set name = 'lizhengi' where id=1;
  1. 在执行前需要:① 连接器连接数据库;② 分析器通过词法分析和语法分析知道这是一条更新语句;③ 优化器决定要使用的索引等;④ 执行器负责具体的执行过程;

  2. 事务开始,从内存(buffer poll)或磁盘(data file)取到包含这条数据的数据页,返回给 Server 的执行器;

  3. Server 的执行器修改数据页的这一行数据的值为 lizhengi

  4. 记录 name=lisa(原值)到 Undo Log;

  5. 记录 name=lizhengi 到 Redo Log;

  6. 调用存储引擎接口,记录数据页到 buffer pool(修改 name= lizhengi);

  7. 事务提交。

相关文章:

【MySQL 系列】MySQL 架构篇

在我们开始了解 MySQL 核心功能之前,首先我们需要站在一个全局的视角,来看 SQL 是如何运作执行的。通过这种方式,我们可以在头脑中构建出一幅 MySQL 各组件之间的协同工作方式,有助于我们加深对 MySQL 服务器的理解。 文章目录 1、…...

C++初阶:类与对象(初篇)

目录 1. 类与对象1.1 引子:结构体与类1.2 什么是类(类的定义方式)1.3 类和结构体的区别1.4 类的访问限定符与封装1.4.1 访问限定符1.4.2 类的作用域与类的实例化 1.5 类对象的模型1.5.1 类内部资源的存储方式1.5.3 类大小的计算方式 1.6 this…...

Docker 创建容器并指定时区

目录 1. 通过环境变量设置时区(推荐)2. 挂载宿主机的时区文件到容器中3. 总结 要在 Docker 容器中指定时区,可以通过两种方式来实现: 1. 通过环境变量设置时区(推荐) 在 Docker 运行时,可以通…...

springboot文件上传修改临时文件路径

1、配置:spring.servlet.multipart.location/data/tmp 2、代码 Configuration public class MultipartConfig {Value("${spring.servlet.multipart.location}")private String tmpLocation;Beanpublic MultipartConfigElement multipartConfigElement()…...

testvue-新增图表功能(教师那边-后续放到管理员那边)-src/main.js ,router/index.js

1.安装--然后在src/main.js中 导入 和 使用2修改&#xff1a;common/sidebar.vue ,page/ echarts.vue , router/index.js , src/main.js 3sidebar.vue <template><div class"sidebar"><el-menuclass"sidebar-el-menu":default-active&quo…...

[HackMyVM]Quick 2

kali:192.168.56.104 主机发现 arp-scan -l # arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:d2:e0:49, IPv4: 192.168.56.104 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.56.1 0a:00:27:00:00:05 (Un…...

Mybatis-Plus实现Service封装

文章目录 5.1 MP封装Service介绍5.1.1 说明5.1.2 实现流程5.1.3 核心API介绍 5.2 MP封装Service快速入门5.2.1 定义服务扩展接口5.2.2 定义服务实现5.2.3 测试测试 5.3 MP封装Service实现CRUD操作 5.1 MP封装Service介绍 5.1.1 说明 MybatisPlus为了开发更加快捷&#xff0c;…...

平台工程指南:从架构构建到职责分工

平台工程只是 DevOps 专业化的另一个术语&#xff0c;还是另有所指&#xff1f;事实可能介于两者之间。DevOps 及其相关的 DevXOps 有着浓厚的文化色彩&#xff0c;以各个团队为中心。不幸的是&#xff0c;在许多地方&#xff0c;DevOps 引发了新的问题&#xff0c;如工具激增和…...

Docker系列之docker与docker-compose离线安装

docker离线安装 一、离线安装包二、安装命令三、配置四、docker-compose 一、离线安装包 上传离线安装包至/root/目录下&#xff0c;docker离线安装包下载链接。 二、安装命令 cd /root mkdir k8sOfflineSetup tar -xzvf k8sOfflineSetup-2020-02-20.tar.gz -C k8sOfflineSe…...

css flex 布局换行

默认使用display: flex;是不换行的&#xff0c;只需要加上flex-wrap: wrap;就行了&#xff0c;效果图 .app-center {display: flex;flex-wrap: wrap;justify-content:flex-start; } 通过上面我们发现虽然时间换行了&#xff0c;但是每行的边距不一样 加上这个就行了&#xff…...

使用腾讯云快速搭建WordPress网站流程详解

专栏系列文章&#xff1a; WordPress建站主题美化系列教程https://blog.csdn.net/seeker1994/category_12184577.html 一文搞懂WordPress是什么&#xff1f;为什么用它建站&#xff1f;怎么安装与部署&#xff1f; 初次安装WordPress后如何进行网站设置&#xff08;主题安装、…...

JavaScript发展历史与JavaScript的版本发展

JavaScript是一种具有函数优先的轻量级&#xff0c;解释型或即时编译型的编程语言。它最初由Netscape公司的Brendan Eich设计&#xff0c;并于1995年在网景导航者浏览器上首次实现。由于Netscape与Sun合作&#xff0c;并希望其外观与Java相似&#xff0c;因此被命名为JavaScrip…...

零基础如何系统自学Python

零基础系统自学Python 学习前的准备 明确学习目标 Python 一共有两大版本&#xff0c;即 Python2 以及 Python3&#xff0c;Python2 已停止维护&#xff0c;强烈建议直接上手 Python3。Python 可以说是无所不能&#xff0c;主要有以下几大方向&#xff0c;建议选择自己感兴趣…...

华为OD机试 - 字符串统计(Java 2024 C卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述1、输入2、输出3、说明 四、解题思路五、Java算法源码六、效果展示1、输入2、输出3、说明 华为OD机试 2024C卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&a…...

LeetCode-数组-前缀和-中等难度

前缀和 前缀和是一种利用预处理的方式来减少整体实现复杂度的方法。 基本定理 假设原数列A为&#xff1a;[1,2,3,4,5]&#xff0c;与之对应的前缀和数列P则为&#xff1a;[1,3,6,10,15] 前缀和数列的第一项等于原数列的第一项&#xff0c;从第二项开始前缀和数列每一项计算…...

【程序人生】探索2024年AI辅助研发趋势

目录标题 探索2024年AI辅助研发趋势一、AI在编码中的应用智能代码生成助力开发错误检测与修复的即时反馈性能优化的智能建议 二、AI驱动的自动化工具三、AI与团队协作四、未来展望结语 探索2024年AI辅助研发趋势 随着人工智能技术的迅速发展&#xff0c;AI在各个领域的应用正日…...

集合框架(一)Collection

学习过了ArrayList&#xff0c;知道集合是一种容器&#xff0c;用来装数据的&#xff0c;类似于数组&#xff0c;但集合的大小可变&#xff0c;开发中也非常常用。 为了满足不同的业务场景需求Java还提供了很多不同特点的集合给我们选择。 集合体系结构 Collection是一个接口&a…...

Android 性能优化--APK加固(2)加密

文章目录 字符串加密图片加密如何避免应用被重新签名分发APK 加壳的方案简析DEX加密原理及实现 本文首发地址&#xff1a;https://h89.cn/archives/212.html 最新更新地址&#xff1a;https://gitee.com/chenjim/chenjimblog 通过 前文 介绍&#xff0c;我们知晓了如何使用代码…...

Linux环境下使用interrupt方式操作UART

目录 概述 1 Linux环境下UART设备 2 轮询方式操作UART功能实现 2.1 打开串口函数&#xff1a;usr_serial_open 2.2 关闭串口函数&#xff1a; usr_serial_close 2.3 发送数据函数&#xff1a; usr_serial_sendbytes 2.4 接收数据函数&#xff1a; usr_serial_readinterr…...

修改Android打包apk的名字和目录

app打包生成apk后通常需要进行备份&#xff0c;但是要区分好哪个apk是什么版本的、什么时候打包的&#xff0c;以方便以后区分使用。 最开始的想法是把版本号、创建时间这些加在apk文件名上即可&#xff0c;但是公司要求apk使用一个固定的名称&#xff0c;那我怎么保存版本号信…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

PL0语法,分析器实现!

简介 PL/0 是一种简单的编程语言,通常用于教学编译原理。它的语法结构清晰,功能包括常量定义、变量声明、过程(子程序)定义以及基本的控制结构(如条件语句和循环语句)。 PL/0 语法规范 PL/0 是一种教学用的小型编程语言,由 Niklaus Wirth 设计,用于展示编译原理的核…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

大学生职业发展与就业创业指导教学评价

这里是引用 作为软工2203/2204班的学生&#xff0c;我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要&#xff0c;而您认真负责的教学态度&#xff0c;让课程的每一部分都充满了实用价值。 尤其让我…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)

引言 工欲善其事&#xff0c;必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后&#xff0c;我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集&#xff0c;就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...