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

PostgreSQL(二十二)缓冲区管理器

目录

一、缓冲区概述

1、缓冲区结构

2、buffer_tag结构

3、Backend进程读取操作

4、写脏块

二、缓冲区管理器结构

1、第一层:Buffer Table layer(缓冲区表层)

2、第二层:Buffer Descriptor Layer(缓冲区描述层)

3、第三层:buffer pool layer

4、数据的访问过程

三、缓冲区管理器锁(Buffer Manager Locks)

1、表层的锁

2、描述层的锁

3、spin lock--自旋锁/旋转锁

四、缓冲区管理器的工作原理

1、情况1:访问已存放在缓冲区中的数据块

2、情况2:加载数据块到空的缓冲池插槽

3、情况3:加载数据块到一个需要释放的缓冲池插槽

4、缓冲区块替换机制

五、环形缓冲区(Ring Buffer)

1、Bulk-reading

2、Bulk-writing

3、Vacuum-processing

六、共享池缓冲区参数设置

1、shared_buffers参数设置

2、wal_buffers 参数设置

3、effective_cache_size参数设置


一、缓冲区概述

1、缓冲区结构

缓冲区:存放各种类型的数据块

(1)数据文件页、表和索引块

(2)可用空间地图块(fsm)

(3)可见性地图块(_vm)

(4)缓冲区数组索引--buffer_ids

2、buffer_tag结构

(1)RelFileNode:分别为表对象oid、数据块oid、表空间oid

(2)页面的fork number(分别为0、1、2)(0=表和索引块,1=fsm,2=vm)

(3)页面number(页面属于哪个块)

示例:缓冲区标记:{(16821、16384、37721)、0、7}

(1)7=标识第7个块中的页

(2)0=fork号,0表明这是存放表数据的数据块

(3)37721=对象号(关系号,OID),表明是属于哪个对象的

(4)16384=数据库OID,说明该块的内容属于OID为16384的数据库

(5)16821=表空间OID,说明该块的内容属于OID 16821的表空间。

3、Backend进程读取操作

后台进程读取数据块到缓冲区的流程(图解)

4、写脏块

下面进程工作时会导致脏块写(将脏页刷新到存储区):

(1)checkpointer(检查点进程):

--将从上一个检查点以来到当前检查点为止,产生的脏块,全都写入磁盘。

--检査点进程将检査点记录写入WAL段文件,并在检查点启动时刷新脏页。

--ckpt的写是一个I/O密集型的写。

(2)background writer(后台写进程)

--后台写进程bgwr持续一点一点地刷新脏页,对数据库活动的影响最小。

--后台写进程的作用是可以减少检查点密集写的影响。

--后台写进程每200毫秒唤醒一次(由bgwriter_delay定义),最多刷新100页(由bgwriter_Iru_maxpages定义)(默认情况下)。

tip:类比oracle的bgwr和ckpt进程,不同的是:

在oracle中,ckpt会给bgwr一个写的信号,由bgwr完成全部的脏块写动作。

在PG中,检査点与后台写进程分离。pg的ckpt自己也会执行脏块写的动作,与bgwr一起写。

相比之下,PG后台写进程独立的方式可以减少ckpt在写时的I/O密集程度。

二、缓冲区管理器结构

Buffer manager’s three-layer structure--缓冲区管理器的三层结构(图解)

1、第一层:Buffer Table layer(缓冲区表层)

在这一层内置的hash函数将buffer_tags映射到插槽,插槽中记录了buffer_tags和描述层的buffer_id的映射关系。

2、第二层:Buffer Descriptor Layer(缓冲区描述层)

本层描述内容包含:buffer_tag与缓冲池插槽id的映射关系,访问次数统计,锁等信息

(1)tag:数据块的tag

(2)buffer_id:缓冲池ID

(3)refcount:记录块被访问的次数。

(4)usage_count:使用的次数,与refcount相关。两者配合使用。

(5)countext_lock and io_in_progress_lock:锁信息。访问内存缓冲区时,需要进行加锁保护。

(6)flags:内存块的标记

       --dirty bit:脏块

       --valid bit:有效块(脏块的内容被写到磁盘后,原本的脏块就变为有效块)

       --io_in_progress bit:正在写/处理的块

(7)freeNext

3、第三层:buffer pool layer

缓冲池是存储数据文件页(如表、索引)的简单数组。缓冲池数组的索引称为buffer_ids;

缓冲池被分割成大小为8k的插槽,等于页面大小。因此,每个槽可以存储整个页面。

4、数据的访问过程

第一次访问一个数据块(在缓冲区全为空时),缓冲区管理器是怎么做的:

(1)先请求一个缓冲区空间,再buffer table 层把描述层的buffer_id把buffer_tag进行映射;

(2)然后在描述层把buffer_tag与缓冲区id进行映射;

(3)最后把数据块读到相应的缓冲区槽。

访问数据块时,要怎么做:

(1)先通过buffer table层,获取A块的插槽id=0

(2)通过ID=0定位到Buffer Descriptor层,找到对应的插槽,在插槽中获得对应的buffer_id

(3)将获取的buffer_id告诉后端进程,然后后端进程根据这个buffer_id来直接访问缓冲区

三、缓冲区管理器锁(Buffer Manager Locks)

缓冲区管理器为许多不同的目的使用许多锁;

锁是缓冲区管理器同步机制的一部分,它们与任何SQL语句和SQL选项都不相关。

1、表层的锁

BufMappingLock保护整个缓冲表的数据完整性。它是一个轻量锁,可以在共亨和独占模式下使用。

在缓冲区表中搜索条目时,后端进程保存共亨的BufMappingLock。当插入或删除条目时,后端进程持有独占锁。

2、描述层的锁

每个缓冲区描述符使用两个轻量级锁

(1)content_lock:内容锁。典型的强制访问限制的锁。它可以用于共享和独占模式。

       当执行下列操作之一时,将获取独占内容锁:

              --dml操作

              --物理删除元组或压缩存储页上的可用空间(Vacuum操作和HOT处理)

              --冻结存储页中的元组

(2)io_in_progress_lock:用于等待缓冲区上的I/O完成(对数据块进行操作时)。

当pg进程从存储区加载/写入页面数据时,该进程在访问存储器时持有相应描述符的独占io_in_progress锁。

3、spin lock--自旋锁/旋转锁

如何固定缓冲区描述符:

(1)获取缓冲区描述符的自旋锁

(2)将其refcount和usage_count的值增加1

(3)松开旋转锁

如何将脏位设置为“1”:

(1)获取缓冲区描述符的自旋锁

(2)使用按位操作将脏位设置为“1”

(3)松开旋转锁

四、缓冲区管理器的工作原理

1、情况1:访问已存放在缓冲区中的数据块

(1)后端进程访问表层相关插槽;

(2)获取共享模式的BufMapping锁;

(3)通过表层获得对应描述层的插槽ID(id=2);

(4)在描述层通过获得的插槽id,获取缓冲区的buffer id;

(5)释放锁;

(6)后端进程依据获得的buffer id,直接访问缓冲池的内容,获得数据。

2、情况2:加载数据块到空的缓冲池插槽

(1)后台进程没有在缓冲区中发现这个数据块;

(2)从描述层中分配一个可用的插槽,返回插槽id

(3)获取独家模式的BufMapping锁;

(4)在表层绑定tag与id信息;

(5)将磁盘中的数据块内容读取到缓冲池;

(6)释放锁;

(7)后台进程利用从描述层获取的buffer id,直接访问缓冲区内容。

3、情况3:加载数据块到一个需要释放的缓冲池插槽

核心:先释放、再加载

(1)后台进程发现目标数据不在缓冲池中。

(2)在描述层寻找可用的插槽,发现目前插槽已满。

然后根据替换机制规则,判断出F是一个可以老化出去的块。然后将这个块的空间释放,用于存储现在需要查询的数据块。

(3)目前这个内存块存储的还是原本Tag_F映射的buffer id对应的磁盘内容;

(4)获取旧的独家模式的BufMapping锁;

(5)获取新的独家模式的BufMapping锁,并在表层插入一条新的条目。此时在表层就会有两个记录的tag同时指向了同一个描述层id(接下来的步骤需要给旧的删除);

(6)删除旧条目,释放旧的独家模式的BufMapping锁(删除后,映射关系失效);

(7)将当前需要查询的数据,从磁盘中读取到缓冲区中;

(8)释放之前获取的新的独家模式的BufMapping锁;

(9)后台进程根据获取的buffer id直接访问缓冲区读取数据。

4、缓冲区块替换机制

替换页面算法

8.1以前:LRU算法

        最近最少使用原则:热度高的表放到LRU的列表头部,热度低了就被放到列表末尾,老化放在末尾的表。

8.1及以后:时钟扫描算法

       缓冲区描述符显示为蓝色或青色框,框中的数字显示每个描述符的使用计数,每扫描一次则-1,缓冲区每被访问过一次则+1

当时钟扫描到refcount=0时,此块将会被老化。否则重复循环扫描,直到扫到0为止

五、环形缓冲区(Ring Buffer)

        当业务需要一个大块的缓冲池时,假如扫描了超过四分之一缓冲池空间(共享缓冲区/4)时,还没有找到足够的可用缓冲池,则会新分配一个环形缓冲区。这个新分配的环形缓冲池就被称为ring-buffer。

        这种情况一般会出现在大数据块操作时,例如:bulk-reading(大量加载)、bulk-writing(大量写)、vacuum-processing(空间整理).

        优点:不会因为某个特殊的大业务动作,来影响已经使用的数据缓冲区,起到一个保护作用,提高缓冲区重复利用率,降低磁盘I/O。

1、Bulk-reading

当大量加载业务需要大块的缓冲池切扫描了超过四分之一缓冲池还没找到,则会分配一个256KB的ring-buffer。

2、Bulk-writing

当大量写业务出现这种情况,会分配一个16MB的ring-buffer。

执行下面列出的sql命令时,会触发大量写业务:

       (1)COPY FROM command.

       (2)CREATE TABLE AS command.

       (3)CREATE MATERIALIZED VIEW    or    REFERSH MATERIALIZED VIEW command.

       (4)ALTER TABLE command.

3、Vacuum-processing

当自动真空机进行真空处理时出现这种情况,会分配一个256KB的ring-buffer。

六、共享池缓冲区参数设置

1、shared_buffers参数设置

show shared_buffers;
Alter system set shared_buffers=256M;

2、wal_buffers 参数设置

show wal_buffers;
Alter system set wal_buffers =4M

3、effective_cache_size参数设置

show effective_cache_size;

这个参数提供可用于磁盘高速缓存的内存量的估计值。它只是一个建议值,而不是确切分配的内存或缓存大小。它不会实际分配内存,而是会告知优化器内核中可用的缓存量。

这个值会影响执行SQL时是选择全表扫描还是优化器的决策。在一个索引的代价估计中,更高的数值会使得索引扫描更可能被使用,更低的数值会使得顺序扫描(全表扫描)更可能被使用。

在设置这个参数时,还应该考虑 Postgresql的共享缓冲区以及将被用于 Postgresql数据文件的内核磁盘缓冲区。

默认值是4GB。不建议修改,除非对于这个参数的理解以及数据库业务场景非常了解、笃定修改后会提高性能(大佬可以玩,菜鸡不要动)。

相关文章:

PostgreSQL(二十二)缓冲区管理器

目录 一、缓冲区概述 1、缓冲区结构 2、buffer_tag结构 3、Backend进程读取操作 4、写脏块 二、缓冲区管理器结构 1、第一层:Buffer Table layer(缓冲区表层) 2、第二层:Buffer Descriptor Layer(缓冲区描述层…...

流程制造业与离散制造业有何差异?流程行业智能制造关注什么?

在当今快速发展的工业领域,智能制造已经成为推动制造业转型升级的关键力量。随着“工业4.0”概念的提出,智能制造的理念和技术被广泛应用于各个制造行业,包括离散制造业和流程制造业。尽管智能制造的起源和发展在很大程度上受到了离散制造业的…...

【论文速读】《面向深度学习的联合消息传递与自编码器》,无线AI的挑战和解决思路

这篇文章来自华为的渥太华无线先进系统能力中心和无线技术实验室,作者中有大名鼎鼎的童文。 一、自编码架构的全局收发机面临的主要问题 文章对我比较有启发的地方,是提到自编码架构的全局收发机面临的主要问题: 问题一:基于随…...

C++从入门到起飞之——输入输出!

目录 1.命名空间 1.1namespace的价值 1.2namespace的定义 1.3命名空间使⽤ 2.C输⼊&输出 3.完结散花 个人主页:秋风起,再归来~ C从入门到起飞 个人格言:悟已往之不谏,知来者犹可追 克心守己…...

米文AD10配置gmsl摄像头操作

一、进入桌面快捷方式 0、设置摄像头型号 miivii_websettings.desktop 设置摄像头 1、获取camera信息 cat /var/log/gmsl_camera.lognvidiamiivii-tegra:~$ cat /var/log/gmsl_camera.log attestationVerify [13] succeed. [INFO ]: miivii gmsl service start! [INFO ]: V…...

【Selenium配置】WebDriver安装浏览器驱动(ChromeEdge)

【Selenium配置】WebDriver安装浏览器驱动(Chrome&Edge) 文章目录 【Selenium配置】WebDriver安装浏览器驱动(Chrome&Edge)Chrome确认Chrome版本下载对应driver把解压后的chromedriver文件放在chrome安装目录下&#xff0…...

预测算法面试

这次面试的是一个预测算法的岗位。虽然我对供应链相关的预测很厌烦了,但是这个不是供应链领域的,感觉应该还好。 首先在介绍工作经历和项目部分,这次面试没有上来没有条理乱说一气,而是预测目标、算法架构、各种使用特征这些分层…...

号称世界上第一个开源实时翻译的 App,微软开源GraphRAG:极大增强大模型问答、摘要、推理,以及开源基于ChatGPT的超级文本代码智能体(附代码地址)

号称世界上第一个开源实时翻译的 App,微软开源GraphRAG:极大增强大模型问答、摘要、推理,以及开源基于ChatGPT的超级文本代码智能体(附代码地址) 在「端侧」上实现可离线的「实时同传」翻译,支持 29 语言的…...

PyTorch 2-深度学习-模块

PyTorch 2-深度学习-模块 一: pytorch1> pytorch 介绍2> pytorch 作用3> pytorch 优点4> pytorch 流程二:pytorch 模块1> torch.Tensor 模块2> torch.nn模块3> torch.nn.function模块4> torch.random模块5> torch.onnx模块6> torch.sparse模块7…...

【MyBatis】MyBatis 理论 40 问(二)

《MyBatis 理论 40 问》包含以下 2 篇文章: MyBatis 理论 40 问(一)MyBatis 理论 40 问(二) MyBatis 理论 40 问(二) 21.如何获取生成的主键?22.当实体类中的属性名和表中的字段名不…...

数据分析——Python网络爬虫(三){爬虫基本原理}

爬虫基本原理 爬虫基本流程拉取什么数据JavaScript渲染页面cookies爬虫代理检查robots.txt爬虫的攻与防 爬虫基本流程 • 获取网页源代码:通过库来实现,urllib,requests等实现http请求    • 提取信息:分析网页源代码&#xff0…...

Linux 忘记root密码,通过单用户模式修改

银河麒麟桌面操作系统 V10(sp1)”忘记用户密码,需要修改用户密码所写,可用于 X86 架构和 arm 架构。 2. 选择第一项,在上图界面按“e”键进行编辑修改。 3. 在以 linux 开头这行的行末,添加“init/bin/bas…...

安卓热门面试题二

什么是AndroidManifest.xml文件?它包含了哪些重要信息? AndroidManifest.xml文件是Android应用程序的全局配置文件,每个Android应用程序的根目录中都必须包含一个AndroidManifest.xml文件,且文件名不能修改。这个文件对于Android…...

agents 分类

一、分类 自动agent、半自动agent、领域、自定义sop和支持人为干预的agent。 先泼个冷水,目前这些agent项目都是实验品,发展还没有做知识库问答相关开源项目那么成熟, 二、全自动agent autoGPT、loopGPT、babyAGI 全自动agent就是人类不可…...

【期末考试复习】概率论与数理统计(知识点模式 - 复习题2)

题目&#xff1a; 设随机变量 X X X 的概率密度函数为 f ( x ) a b x f(x) a bx f(x)abx&#xff0c;其中 0 < x ≤ 1 0 < x \leq 1 0<x≤1&#xff1b; f ( x ) 0 f(x) 0 f(x)0&#xff0c;在其他情况下。已知 P ( X ≤ 1 / 2 ) 3 / 8 P(X \leq 1/2) 3/…...

Jetpack Compose实现一个简单的微信UI

https://blog.csdn.net/News53231323/article/details/128509048 https://franzliszt1847.blog.csdn.net/article/details/129344822...

myeclipse开发ssm框架项目图书管理系统 mysql数据库web计算机毕业设计项目

摘 要 随着计算机的广泛应用&#xff0c;其逐步成为现代化的标志。图书馆的信息量也会越来越大&#xff0c;因此需要对图书信息、借书信息、还书信息等进行管理&#xff0c;及时了解各个环节中信息的变更&#xff0c;要对因此而产生的单据进行及时的处理&#xff0c;为了提高高…...

网络安全防御 -- 防火墙安全策略用户认证综合实验

实验拓扑&#xff1a; 实验目的&#xff1a; 1、DMZ区内的服务器&#xff0c;办公区仅能在办公时间内(9:00-18:00)可以访问&#xff0c;生产区的设备全天可以访问。 2、生产区不允许访问互联网&#xff0c;办公区和游客区允许访问互联网。 3、办公区设备10.0.2.10不允许访问DM…...

捷配笔记-PCB阻焊颜色对产品有什么影响?

阻焊层也称为阻焊层或阻焊剂。它是一种薄的聚合物层&#xff0c;应用于&#xff08;PCB&#xff09;。阻焊层的目的是保护PCB表面&#xff0c;并有助于防止焊桥。焊桥是两个导体之间的无意连接&#xff0c;通常是由于存在一小块焊料。需要注意的是&#xff0c;阻焊层被视为其单…...

网信大数据信用报告查询怎么查?网信大数据有什么作用?

随着互联网的快速发展&#xff0c;大数据技术已经广泛应用于各行各业。其中&#xff0c;网信大数据信用报告查询成为了许多人关注的焦点。那么&#xff0c;如何查询网信大数据信用报告呢?网信大数据又有哪些作用呢?本文将为您一一解答。 一、如何查询网信大数据信用报告? 要…...

【Vue】vue-element-admin组件化功能

1. 组件的封装 在vue-element-admin中&#xff0c;每个功能区域或UI元素都被封装成一个或多个Vue组件。这些组件可以是简单的按钮、输入框&#xff0c;也可以是复杂的表格、表单或页面布局。每个组件都包含了其模板&#xff08;HTML结构&#xff09;、逻辑&#xff08;JavaScr…...

[论文笔记]涨点近5%! 以内容中心的检索增强生成可扩展的级联框架:Pistis-RAG

引言 今天带来一篇较新RAG的论文笔记&#xff1a;Pistis-RAG: A Scalable Cascading Framework Towards Content-Centric Retrieval-Augmented Generation。 在希腊神话中&#xff0c;Pistis象征着诚信、信任和可靠性。受到这些原则的启发&#xff0c;Pistis-RAG是一个可扩展…...

时钟系统框图(时钟树)解析

时钟系统框图&#xff08;时钟树&#xff09;解析 文章目录 时钟系统框图&#xff08;时钟树&#xff09;解析1、时钟树2、 4个时钟源&#xff1a;HSI、HSE、LSI、LSE3、PLL锁相环倍频输出4、系统时钟的来源5、Enable CSS&#xff08;时钟监视系统&#xff09;6、几个重要的时钟…...

DNS缓存详解

目录 一、缓存分类 1. 客户端缓存&#xff08;以浏览器缓存为列&#xff09; 2. 操作系统缓存 3.本地hosts文件静态映射 二、DNS查找优先顺序 1.浏览器查找顺序 2.cmd ping查找顺序&#xff08;非浏览器&#xff09; 一、缓存分类 在一台终端上&#xff0c;DNS缓存可以…...

一款好用的特殊字符处理工具

跟mybatis代码的时候&#xff0c;偶然发现的一款特殊字符处理工具java.lang.StringTokenizer。平常&#xff0c;我们看到的mybatis mapper.xml里面各种换行各种缩进&#xff0c;但日志文件里面的sql都是整整齐齐的。没有换行符&#xff0c;缩进等。就是利用该工具做的格式化处理…...

双重锁定:零信任沙箱 完美的安全保障

在当今数字化的世界中&#xff0c;企业的数据安全已成为至关重要的一环。随着云计算、移动互联和物联网等新技术的不断发展&#xff0c;传统的安全边界逐渐模糊&#xff0c;访问控制模式的局限性也日益凸显。为了应对这些挑战&#xff0c;零信任安全模型和苏州深信达的SDC沙盒技…...

【小沐学Python】在线web数据可视化Python库:Bokeh

文章目录 1、简介2、安装3、测试3.1 创建折线图3.2 添加和自定义渲染器3.3 添加图例、文本和批注3.4 自定义您的绘图3.5 矢量化字形属性3.6 合并绘图3.7 显示和导出3.8 提供和筛选数据3.9 使用小部件3.10 嵌入Bokeh图表到Flask应用程序 结语 1、简介 https://bokeh.org/ https…...

GitHub 站点打不开

遇到的问题 您是否遇到过GitHub网站打不开的情况&#xff0c;正如下图所示&#xff1a; 解决方案 以下是一些常见的解决方案&#xff1a; 1. 检查网络连接 确保你的设备已连接到互联网。尝试访问其他网站&#xff0c;确保不是你的网络问题。 C:\Vinca>ping github.…...

前端开发工具

Lodash 有普通的 CommonJS 版本&#xff08;通常称为 lodash&#xff09;和 ES6 模块版本&#xff08;称为 lodash-es&#xff09;。它们的主要区别包括&#xff1a; 模块化&#xff1a;lodash 是传统的 CommonJS 模块&#xff0c;可使用 require 或 import 引入&#xff1b;lo…...

Everything搜索无法搜索到桌面的文件(无法检索C盘 或 特定路径的文件)

现象描述 在Everything搜索框中输入桌面已存在的文件或随便已知位置的文件&#xff0c;无法找到。 搜索时检索结果中明显缺少部分磁盘位置的&#xff0c;例如无法检索C盘&#xff0c;任意关键字搜索时结果中没有位于C盘的&#xff0c;无论怎样都搜不到C盘文件。 解决方法 在…...

整合营销网站/seo是什么意思中文

原标题&#xff1a;一款卡通风格的“类恶魔城”独立游戏HELLO&#xff5e;大家好&#xff0c;这里是小白的每日一游推荐时间。世上的游戏千千万&#xff0c;有许多好玩的游戏由于缺乏宣传&#xff0c;所以不被广大玩家所熟知。在这里小白每天会为大家推荐一款评价很高但是不太出…...

织梦网站主页/竞价推广和seo的区别

https://www.cnblogs.com/fnng/p/6111516.html 最近在整理接口测试相关的资料&#xff0c;所以&#xff0c;看到有关资料就会多看两眼。偶看到别人发的微信公众号。 Python接口测试框第一篇 --- python如何读取txt文件。 Python接口测试框第三篇 --- python如何读取XML文件。 P…...

网站续费通知/百度链接提交入口

Matplotlib是Python中的一个库&#xff0c;它是数字的-NumPy库的数学扩展。轴类包含大多数图形元素&#xff1a;Axis&#xff0c;Tick&#xff0c;Line2D&#xff0c;Text&#xff0c;Polygon等&#xff0c;并设置坐标系。 Axes实例通过callbacks属性支持回调。matplotlib.axes…...

在网上做试卷的网站/服务营销的七个要素

最初接触 speed grade 这个概念时&#xff0c;很是为 Altera 的 -6 、 -7 、 -8 速度等级逆向 排序的方法困惑过一段时间。 不很严密地说&#xff0c; “序号越低&#xff0c; 速度等级越高”这是 Altera FPGA 的排序方法 &#xff0c;“序号越高&#xff0c;速度等级也越高”…...

如何利用视频网站做数字营销推广/百度知道官网首页登录入口

世界上最安全的地方是哪&#xff1f;大部分人的答案是家。而守护家的安全就绝对离不开一扇坚固的防盗门。现在市场上防盗门品牌繁杂&#xff0c;质量参差不齐&#xff0c;都说自己是最好的&#xff0c;最安全的&#xff0c;但其实内里却是别有乾坤。日上防盗门质检工程师告诉我…...

临沂网站建设和轶件安装/电脑优化软件哪个好用

Selenium是一个web自动化测试框架。用它可以实现web应用自动化测试。不过&#xff0c;我不只是用它来做测试&#xff0c;我还用它从电子商务网站签到页面爬取javascript生成的或AJAX的内容。 作为程序员&#xff0c;我不满足于使用Selenium IDE来记录和重放宏记录。那样很蹩脚&…...