SQLite轻量级会话扩展(三十四)

news2024/11/15 13:49:07

返回:SQLite—系列文章目录   

上一篇:SQLite R*Tree 模块(三十三)

下一篇:SQLite—系列文章目录   

1. 引言

会话扩展提供了一种方便记录的机制 对 SQLite 数据库中某些表的部分或全部更改,以及 将这些更改打包到“变更集”或“补丁集”文件中,可以 稍后用于将同一组更改应用于另一个数据库 相同的架构和兼容的起始数据。“变更集”可能 也可以倒置并用于“撤消”会话。

本文档是对会话扩展的介绍。 该接口的详细信息位于单独的会话扩展 C 语言接口文档中。

1.1. 典型用例

假设 SQLite 被用作应用程序文件格式 特定的设计应用。两个用户 Alice 和 Bob 分别启动 基线设计大小约为 1 GB。他们工作 一整天,并行,每个人都在进行自己的定制和调整 到设计。归根结底,他们想合并他们的 一起改变成一个统一的设计。

会话扩展通过记录对 Alice 和 Bob 的数据库,并将这些更改写入 变更集或补丁集文件。在一天结束时,爱丽丝可以送她 changeset 到 Bob,Bob 可以将其“应用”到他的数据库中。结果(假设 没有冲突)是 Bob 的数据库包含他的 变化和爱丽丝的变化。同样,Bob 可以发送 他的工作交给了爱丽丝,她可以将他的更改应用到她的数据库中。

换言之,会话扩展提供了以下工具: 类似于 unix 补丁实用程序的 SQLite 数据库文件, 或版本控制系统的“合并”功能,例如 饰演 Fossil, Git, 或Mercurial。

1.2. 获取会话扩展

自 3.13.0 版(2016-05-18)起, 会话扩展已包含在 SQLite 合并源分发中。默认情况下,会话扩展为 禁用。若要启用它,请使用以下编译器开关进行生成:

-DSQLITE_ENABLE_SESSION -DSQLITE_ENABLE_PREUPDATE_HOOK

或者,如果使用 autoconf 构建系统, 将 --enable-session 选项传递给 configure 脚本。

1.3. 限制

  • 在 SQLite 版本 3.17.0 之前,会话扩展仅适用于 rowid 表,而不适用于 ROWID 表。从 3.17.0 开始,两者都 支持 rowid 和 WITHOUT ROWID 表。但是,额外的步骤是 需要记录 WITHOUT ROWID 表更改的主键。

  • 不支持虚拟表。对虚拟表的更改包括 未捕获。

  • 会话扩展仅适用于声明了 主键。表的 PRIMARY KEY 可以是 INTEGER PRIMARY KEY (rowid 别名)或外部 PRIMARY KEY。

  • SQLite 允许将 NULL 值存储在 PRIMARY KEY 列。但是,会话扩展会忽略所有 这样的行。不会影响具有一个或多个 NULL 值的行的更改 在 PRIMARY KEY 中,列由 sessions 模块记录。

2. 概念

2.1. 变更集和补丁集

会话模块围绕创建和操作展开 变更集。变更集是编码一系列 对数据库的更改。变更集中的每个更改都是 以后:

  • 一个 INSERT。INSERT 更改包含要添加到的单行 数据库表。INSERT 更改的有效负载包括 新行的每个字段的值。

  • A 删除。DELETE 更改表示一行,由 其主键值,要从数据库表中删除。有效载荷 的 DELETE 更改由 已删除的行。

  • 更新。UPDATE 更改表示对 数据库中单行的一个或多个非 PRIMARY KEY 字段 表,由其 PRIMARY KEY 字段标识。UPDATE 的有效负载 更改包括:

    • 标识修改后的行的 PRIMARY KEY 值,
    • 行中每个已修改字段的新值,以及
    • 行中每个已修改字段的原始值。

    UPDATE 更改不包含有关以下方面的任何信息 未被更改修改的非 PRIMARY KEY 字段。事实并非如此 UPDATE 更改可以指定对 PRIMARY 的修改 KEY 字段。

单个变更集可能包含适用于多个变更集的变更 数据库表。对于变更集至少包含一个更改的每个表 因为,它还对以下数据进行编码:

  • 数据库表的名称,
  • 表的列数,以及
  • 这些列中哪一列是 PRIMARY KEY 列。

变更集只能应用于包含表的数据库 匹配变更集中存储的上述三个条件。

补丁集类似于变更集。它比 变更集,但提供更有限的冲突检测和解决 选项(有关详细信息,请参阅下一节)。之间的区别 patchset 和 changeset 是:

  • 对于 DELETE 更改,有效负载由 PRIMARY KEY 组成 仅限字段。其他字段的原始值不存储为 补丁集的一部分。

  • 对于 UPDATE 更改,有效负载由 PRIMARY KEY 组成 字段和仅修改字段的新值。原文 已修改字段的值不会存储为补丁集的一部分。

2.2. 冲突

当变更集或补丁集应用于数据库时,尝试是 为每个 INSERT 更改插入一个新行,为每个更改删除一行 DELETE 更改并修改每个 UPDATE 更改的一行。如果目标 数据库与变更集的原始数据库处于相同的状态 被记录下来,这是一件简单的事情。但是,如果 目标数据库并不完全处于此状态,当以下情况下可能会发生冲突 应用变更集或补丁集。

处理 INSERT 更改时,以下冲突可能 发生:

  • 目标数据库可能已包含具有相同 PRIMARY 的行 由 INSERT 更改指定的 KEY 值。
  • 其他一些数据库约束,例如 UNIQUE 或 CHECK 约束,在插入新行时可能会被违反。

处理 DELETE 更改时,可能会出现以下冲突: 检测:

  • 目标数据库可能不包含具有指定 PRIMARY 的行 要删除的 KEY 值。
  • 目标数据库可能包含具有指定 PRIMARY 的行 KEY 值,但其他字段可能包含不 匹配存储为变更集一部分的那些。这种类型的冲突 使用补丁集时未检测到。

处理 UPDATE 更改时,可能会出现以下冲突: 检测:

  • 目标数据库可能不包含具有指定 PRIMARY 的行 要修改的 KEY 值。
  • 目标数据库可能包含具有指定 PRIMARY 的行 KEY 值,但要修改的字段的当前值 通过更改可能与存储在 变更集。使用修补程序集时,不会检测到此类冲突。
  • 其他一些数据库约束,例如 UNIQUE 或 CHECK 约束,更新行时可能会被违反。

根据冲突的类型,会话应用程序具有多种 用于处理冲突的可配置选项,范围从省略 冲突的更改、中止整个变更集应用程序或应用 尽管存在冲突,但变化。有关详细信息,请参阅文档 sqlite3changeset_apply() API。

2.3. 变更集构造

配置会话对象后,它将开始监视 对其配置表的更改。但是,它不会记录整个 每次修改数据库中的行时进行更改。相反,它会记录 仅插入每个行的 PRIMARY KEY 字段,以及 PRIMARY KEY 以及任何更新或删除的行的所有原始行值。如果一行是 单个会话多次修改,不会记录新信息。

创建变更集或补丁集所需的其他信息包括 调用 sqlite3session_changeset() 或 sqlite3session_patchset() 时从数据库文件中读取。具体说来

  • 对于作为 INSERT 操作结果记录的每个主键, 会话模块检查是否存在具有匹配主节点的行 键仍在表中。如果是这样,则将 INSERT 更改添加到 变更集。

  • 对于作为 UPDATE 或 DELETE 结果记录的每个主键 操作中,会话模块还会检查具有匹配的行 表中的主键。如果可以找到一个,但一个或多个 非 PRIMARY KEY 字段与原始记录不匹配 值,则 UPDATE 将添加到变更集中。或者,如果没有行 使用指定的主键时,DELETE 将添加到 变更集。如果该行确实存在,但没有非主键 字段已修改,变更集不会添加任何更改。

上述的一个含义是,如果进行了更改,然后 在单个会话中取消(例如,如果插入了一行,然后 再次删除),会话模块根本不会报告任何更改。或 如果同一会话中同一行多次更新,则所有更新 合并到任何变更集或修补程序集 blob 中的单个更新中。

3. 使用会话扩展

本节提供的示例演示了如何使用会话 外延。

3.1. 捕获变更集

下面的示例代码演示了捕获 执行 SQL 命令时的变更集。综上所述:

  1. 会话对象(类型 sqlite3_session*)是通过创建 调用 sqlite3session_create() API 函数。

    单个会话对象监视对单个数据库所做的更改 (即“main”、“temp”或附加数据库)通过单个 sqlite3* 数据库句柄。

  2. 会话对象配置了一组要监视的表 更改。

    默认情况下,会话对象不会监视任何 数据库表。在执行此操作之前,必须对其进行配置。那里 是配置表集以监视更改的三种方法 上:

    • 通过对每个表使用一次对 sqlite3session_attach() 的调用显式指定表,或者
    • 通过指定应监视数据库中的所有表 对于使用对 sqlite3session_attach() 的调用进行更改,带有 NULL 参数,或者
    • 通过配置每个表首次调用的回调 写入该会话模块,指示会话模块是否或 不应监视表上的更改。

    下面的示例代码使用枚举的第二个方法 上面 - 它监视所有数据库表上的更改。

  3. 通过执行 SQL 语句对数据库进行更改。这 会话对象记录这些更改。

  4. 使用调用从会话对象中提取变更集 Blob to sqlite3session_changeset() (或者,如果使用补丁集,则调用 sqlite3session_patchset() 函数)。

  5. 使用对 sqlite3session_delete() API 函数的调用删除会话对象。

    解压后无需删除会话对象 来自它的变更集或补丁集。它可以留在 数据库句柄,并将继续监视 像以前一样配置了表。但是,如果 sqlite3session_changeset() 或 sqlite3session_patchset() 是 对会话对象、变更集或补丁集进行第二次调用 将包含连接上发生的所有更改 自会话创建以来。换言之, 会话对象未重置或 通过调用 sqlite3session_changeset()或 sqlite3session_patchset()。

/*
** Argument zSql points to a buffer containing an SQL script to execute
** against the database handle passed as the first argument. As well as
** executing the SQL script, this function collects a changeset recording
** all changes made to the "main" database file. Assuming no error occurs,
** output variables (*ppChangeset) and (*pnChangeset) are set to point
** to a buffer containing the changeset and the size of the changeset in
** bytes before returning SQLITE_OK. In this case it is the responsibility
** of the caller to eventually free the changeset blob by passing it to
** the sqlite3_free function.
**
** Or, if an error does occur, return an SQLite error code. The final
** value of (*pChangeset) and (*pnChangeset) are undefined in this case.
*/
int sql_exec_changeset(
  sqlite3 *db,                  /* Database handle */
  const char *zSql,             /* SQL script to execute */
  int *pnChangeset,             /* OUT: Size of changeset blob in bytes */
  void **ppChangeset            /* OUT: Pointer to changeset blob */
){
  sqlite3_session *pSession = 0;
  int rc;

  /* Create a new session object */
  rc = sqlite3session_create(db, "main", &pSession);

  /* Configure the session object to record changes to all tables */
  if( rc==SQLITE_OK ) rc = sqlite3session_attach(pSession, NULL);

  /* Execute the SQL script */
  if( rc==SQLITE_OK ) rc = sqlite3_exec(db, zSql, 0, 0, 0);

  /* Collect the changeset */
  if( rc==SQLITE_OK ){
    rc = sqlite3session_changeset(pSession, pnChangeset, ppChangeset);
  }

  /* Delete the session object */
  sqlite3session_delete(pSession);

  return rc;
}

3.2. 将变更集应用于数据库

将变更集应用于数据库比捕获变更集更简单。 通常,对 sqlite3changeset_apply() 的单个调用,如 下面的示例代码就足够了。

在复杂的情况下,应用 变更集在于解决冲突。请参阅链接的 API 文档 以上了解详情。

/*
** Conflict handler callback used by apply_changeset(). See below.
*/
static int xConflict(void *pCtx, int eConflict, sqlite3_changset_iter *pIter){
  int ret = (int)pCtx;
  return ret;
}

/*
** Apply the changeset contained in blob pChangeset, size nChangeset bytes,
** to the main database of the database handle passed as the first argument.
** Return SQLITE_OK if successful, or an SQLite error code if an error
** occurs.
**
** If parameter bIgnoreConflicts is true, then any conflicting changes
** within the changeset are simply ignored. Or, if bIgnoreConflicts is
** false, then this call fails with an SQLTIE_ABORT error if a changeset
** conflict is encountered.
*/
int apply_changeset(
  sqlite3 *db,                  /* Database handle */
  int bIgnoreConflicts,         /* True to ignore conflicting changes */
  int nChangeset,               /* Size of changeset in bytes */
  void *pChangeset              /* Pointer to changeset blob */
){
  return sqlite3changeset_apply(
      db,
      nChangeset, pChangeset,
      0, xConflict,
      (void*)bIgnoreConflicts
  );
}

3.3. 检查变更集的内容

下面的示例代码演示了用于迭代的技术 通过并提取与变更集中的所有更改相关的数据。自 总结:

  1. 调用 sqlite3changeset_start() API 来创建和 初始化迭代器以遍历 变更集。最初,迭代器根本不指向任何元素。

  2. 在迭代器上对 sqlite3changeset_next() 的第一次调用会移动 它指向变更集中的第一个更改(或指向 EOF,如果 变更集完全为空)。sqlite3changeset_next() 返回 SQLITE_ROW 如果它移动迭代器以指向有效条目, SQLITE_DONE是否将迭代器移动到 EOF,或者出现 SQLite 错误 如果发生错误,则进行代码。

  3. 如果迭代器指向有效条目,则 sqlite3changeset_op() API 可用于确定更改类型(INSERT、UPDATE 或 DELETE),迭代器指向。此外,相同的 API 可用于获取更改所适用的表的名称 以及其预期的列数和主键列数。

  4. 如果迭代器指向有效的 INSERT 或 UPDATE 条目,则可以使用 sqlite3changeset_new() API 来获取新的 .* 值 在更改有效负载中。

  5. 如果迭代器指向有效的 DELETE 或 UPDATE 条目,则可以使用 sqlite3changeset_old() API 获取旧的 .* 值 在更改有效负载中。

  6. 使用对 sqlite3changeset_finalize() API 的调用删除迭代器。如果在 迭代时,返回 SQLite 错误代码(即使相同的错误 代码已由 sqlite3changeset_next()) 返回。或 如果未发生错误,则返回SQLITE_OK。

/*
** Print the contents of the changeset to stdout.
*/
static int print_changeset(void *pChangeset, int nChangeset){
  int rc;
  sqlite3_changeset_iter *pIter = 0;

  /* Create an iterator to iterate through the changeset */
  rc = sqlite3changeset_start(&pIter, nChangeset, pChangeset);
  if( rc!=SQLITE_OK ) return rc;

  /* This loop runs once for each change in the changeset */
  while( SQLITE_ROW==sqlite3changeset_next(pIter) ){
    const char *zTab;           /* Table change applies to */
    int nCol;                   /* Number of columns in table zTab */
    int op;                     /* SQLITE_INSERT, UPDATE or DELETE */
    sqlite3_value *pVal;

    /* Print the type of operation and the table it is on */
    rc = sqlite3changeset_op(pIter, &zTab, &nCol, &op, 0);
    if( rc!=SQLITE_OK ) goto exit_print_changeset;
    printf("%s on table %s\n",
      op==SQLITE_INSERT?"INSERT" : op==SQLITE_UPDATE?"UPDATE" : "DELETE",
      zTab
    );

    /* If this is an UPDATE or DELETE, print the old.* values */
    if( op==SQLITE_UPDATE || op==SQLITE_DELETE ){
      printf("Old values:");
      for(i=0; i<nCol; i++){
        rc = sqlite3changeset_old(pIter, i, &pVal);
        if( rc!=SQLITE_OK ) goto exit_print_changeset;
        printf(" %s", pVal ? sqlite3_value_text(pVal) : "-");
      }
      printf("\n");
    }

    /* If this is an UPDATE or INSERT, print the new.* values */
    if( op==SQLITE_UPDATE || op==SQLITE_INSERT ){
      printf("New values:");
      for(i=0; i<nCol; i++){
        rc = sqlite3changeset_new(pIter, i, &pVal);
        if( rc!=SQLITE_OK ) goto exit_print_changeset;
        printf(" %s", pVal ? sqlite3_value_text(pVal) : "-");
      }
      printf("\n");
    }
  }

  /* Clean up the changeset and return an error code (or SQLITE_OK) */
 exit_print_changeset:
  rc2 = sqlite3changeset_finalize(pIter);
  if( rc==SQLITE_OK ) rc = rc2;
  return rc;
}

4. 扩展功能

大多数应用程序将仅使用所描述的会话模块功能 在上一节中。但是,以下附加功能是 可用于使用和操作变更集和修补程序集 Blob:Available for the use and manipulation of changeset and patchset blob:

  • 可以使用 sqlite3changeset_concat() 或 sqlite3_changegroup 接口组合两个或多个变更集/补丁集。

  • 可以使用 sqlite3changeset_invert() API 函数“反转”变更集。反向变更集撤消了 源语言。如果变更集 C+ 是变更集 C 的逆,则 将 C 和 C+ 应用于数据库应该会离开 数据库未更改。

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

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

相关文章

[阅读笔记18][CITING]LARGE LANGUAGE MODELS CREATE CURRICULUM FOR INSTRUCTION TUNING

这篇论文是23年10月提交到arxiv上的&#xff0c;也是用大模型蒸馏小模型的思路。 作者在这篇论文中提出了课程指令微调&#xff0c;大体流程如下图所示&#xff0c;教师模型给出一个问题&#xff0c;让学生模型回答一下&#xff0c;这时候学生回答大概率不够准确&#xff0c;这…

4.2冰达机器人:视觉实例-机器人视觉循线、视觉实例-调整循线颜色

4.2.10a视觉实例-机器人视觉循线 本节内容演示一个机器人视觉的视觉循线实例 准备工作&#xff1a;布置一块区域作为循线场所&#xff0c;如下图所示。用蓝色胶带在地面贴一条路线&#xff08;机器人极限转弯半径0.5m&#xff0c;不要贴得过于曲折&#xff09;&#xff0c;将…

MINIO安装的方法(WindowsLiunx)

2 minio安装教程 注&#xff1a;官方中文文档&#xff1a;MinIO对象存储 Windows — MinIO中文文档 | MinIO Windows中文文档 Liunx 安装方&#xff1a;MinIO对象存储 Linux — MinIO中文文档 | MinIO Linux中文文档 2.1 下载地址 https://dl.min.io/server/minio/…

vlan 和 trunk实验

VLAN&#xff08;Virtual Local Area Network&#xff09;&#xff0c;即虚拟局域网&#xff0c;是一种网络技术&#xff0c;它的主要原理是将物理网络划分为多个逻辑子网&#xff0c;每个子网形成一个独立的广播域。这样&#xff0c;VLAN内的主机间通信就像在同一个局域网内一…

第二届 Oceanbase 开发者大会 实录

第二届 Oceanbase 开发者大会 实录 今天很有幸参加了Oceanbase 开发者大会&#xff0c;我是真的我一开始还不知道什么是Oceanbase &#xff0c;直到我开了会才知道。看来真的需要多参加一些这样活动。 会议议程 我们科普一下什么是Oceanbase OceanBase 是阿里巴巴集团推出…

Junit 高级-ApiHug准备-测试篇-011

&#x1f917; ApiHug {Postman|Swagger|Api...} 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱&#xff0c;有温度&#xff0c;有质量&#xff0c;有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace 涉及到 …

MYSQL之增删改查(下)

前言&#xff1a; 以下是MySQL最基本的增删改查语句&#xff0c;很多IT工作者都必须要会的命令&#xff0c;也 是IT行业面试最常考的知识点&#xff0c;由于是入门级基础命令&#xff0c;所有所有操作都建立在单表 上&#xff0c;未涉及多表操作。 4.3 高级查询 4.3.1 聚合函…

【python】使用python和selenium实现某平台自动化上传作品的全步骤

第一&#xff0c;我们需要下载python并安装 下载地址&#xff1a;https://www.python.org/downloads/release/python-3123/ 3.x版本的python自带pip工具&#xff0c;因此不需要额外下载。 ModuleNotFoundError: No module named seleniumpip用于下载python适用的各类模块&…

最小化横穿北达科他州的直排轮滑补水次数

最小化横穿北达科他州的直排轮滑补水次数 问题定义算法设计伪代码C代码示例策略的正确性和运行时间分析结论 问题定义 Gekko教授计划使用直排轮滑从明尼苏达州东部边境的大福克斯市出发&#xff0c;横穿北达科他州&#xff0c;抵达靠近蒙大拿州西部边境的威利斯顿市。他计划携…

24华中杯ABC题更新完成,B题将提供论文参考,AC题将在下午完成论文

以下内容&#xff0c;将在文章最后放置链接 2024华中杯A题12页思路数据可执行代码参考论文https://mbd.pub/o/bread/ZZ6am5dw 2024华中杯B题24页思路数据可执行代码参考论文https://mbd.pub/o/bread/ZZ6am5hp 2024华中杯C题10页思路数据可执行代码参考论文https://mbd.pub/o/br…

Nginx part2.1

目录 搭建目录网页 为网页设置用户登录 做一个文件目录网页&#xff0c;并进行登陆 示范 搭建目录网页 启动nginx&#xff1a; systemctl start nginx 开机自启动nginx&#xff1a; systemctl enable nginx 启动完服务后&#xff0c;查看自己的nginx的状态&#xff1a;sys…

volatility内存取证

记录一道volatility内存取证的题目&#xff0c;第一次遇到&#xff0c;现场把环境搞出来&#xff0c;现记录一些操作指令。 一、安装volatility3 1、新建一个kali虚拟机 新建的过程不再赘述。 2、下载volatility3 GitHub - volatilityfoundation/volatility3: Volatility …

基于Springboot的职称评审管理系统

基于SpringbootVue的获取源码 联系方式 &#x1f447;&#x1f3fb;的设计与实现 开发语言&#xff1a;Java数据库&#xff1a;MySQL技术&#xff1a;SpringbootMybatis工具&#xff1a;IDEA、Maven、Navicat 系统展示 用户登录 首页 评审条件 论坛信息 系统公告 后台登录…

CTFshow-PWN-前置基础(pwn26-pwn31)

目录 1、pwn26 2、pwn27 3、pwn28 4、pwn29 5、pwn30 6、pwn31 1、pwn26 设置好 ASLR 保护参数值即可获得flag 首先我们需要知道什么是 ASLR&#xff1f; ASLR&#xff08;Address Space Layout Randomization&#xff09;是一种操作系统级别的安全功能&#xff0c;它通…

【VSLAM】VINO-Mono安装部署与运行

&#x1f60f;★,:.☆(&#xffe3;▽&#xffe3;)/$:.★ &#x1f60f; 这篇文章主要介绍VINO-Mono安装部署与运行。 学其所用&#xff0c;用其所学。——梁启超 欢迎来到我的博客&#xff0c;一起学习&#xff0c;共同进步。 喜欢的朋友可以关注一下&#xff0c;下次更新不迷…

数学建模--非线性规划模型+MATLAB代码保姆式解析

目录 1.简单介绍 2.求解方法 3.适用赛题 4.典型例题及相关分析 &#xff08;1&#xff09;问题引入 &#xff08;2&#xff09;决策变量&约束条件 &#xff08;3&#xff09;确定目标函数 &#xff08;4&#xff09;建立数学模型 5.MATLAB代码祝逐字句讲解 1.简单…

什么是AIoT?

什么是AIoT? AIoT&#xff0c;即人工智能物联网&#xff0c;是一种将人工智能&#xff08;AI&#xff09;技术与物联网&#xff08;IoT&#xff09;相结合的新型应用形态。它不仅实现了设备之间的互联互通&#xff0c;还赋予了它们更智能化的特性。AIoT的核心在于通过AI的数据…

Ubuntu 系统安装 VS Code 并配置 C++ 环境

Linux 系列教程&#xff1a; VMware 安装配置 Ubuntu&#xff08;最新版、超详细&#xff09;FinalShell 远程连接 Linux&#xff08;Ubuntu&#xff09;系统Ubuntu 系统安装 VS Code 并配置 C 环境 ➡️➡️ ➡️VS Code 官方教程&#xff1a;Using C on Linux in VS Code&…

掌握字幕艺术:pysrt 库指南

文章目录 掌握字幕艺术&#xff1a;pysrt 库指南第一部分&#xff1a;背景介绍第二部分&#xff1a;库是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;库函数使用方法第五部分&#xff1a;场景应用第六部分&#xff1a;常见Bug及解决方…

基于Kubernetes集群构建MongoDB

基于Kubernetes集群构建MongoDB 作者:行癫(盗版必究) 一:基础环境 1.Kubernetes集群正常运行 2.Harbor私有仓库正常运行 二:MongoDB项目部署 ​ MongoDB项目对应Kubernetes的yaml文件: --- apiVersion: v1 kind: Namespace metadata:name: m