SQLite版本3中的文件锁定和并发(七)

  返回:SQLite—系列文章目录   

上一篇:自己编译SQLite或将SQLite移植到新的操作系统(六)

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

正文:

1.0 SQLite 版本 3 中的文件锁定和并发

SQLite 版本 3.0.0 引入了新的锁定和日志功能 旨在提高 SQLite 版本 2 的并发性的机制 并减少作家的饥饿 问题。新机制还允许交易的原子提交 涉及多个数据库文件。 本文档介绍新的锁定机制。 目标受众是想要理解和/或修改的程序员页面代码和审阅者致力于验证设计 的 SQLite 版本 3。

2.0 概述

锁定和并发控制由页面模块处理。 页面模块负责使 SQLite 成为“ACID”(原子、 一致、隔离和持久)。页面模块确保更改 一下子发生,要么所有的变化都发生,要么没有一个发生, 两个或多个进程不尝试访问数据库 同时以不兼容的方式,并且一旦发生了变化 书面的它们会一直存在,直到被明确删除。页面还提供磁盘文件某些内容的内存缓存。

页面不关心 以及 B 树、文本编码、索引等的详细信息。 从页面的角度来看,数据库由大小均匀的块的单个文件。每个块称为 “page”,大小通常为 1024 字节。页面已编号 从 1 开始。因此,数据库的前 1024 个字节被称为 “第 1 页”和第二个 1024 字节称为“第 2 页”,依此类推。都 其他编码细节由库的更高层处理。 页面使用以下几种之一与操作系统进行通信模块 (例如: os_unix.c、 os_win.c) 这为操作系统服务提供了统一的抽象。

页面模块有效地控制对单独线程的访问,或者单独的进程,或两者兼而有之。在本文档中,每当 写有“进程”一词,您可以用“线程”一词代替,而不使用 改变陈述的真实性。

3.0 锁定

从单个进程的角度来看,数据库文件 可以处于以下五种锁定状态之一:

解 锁数据库上不保留任何锁。数据库可能既不能读取,也不能 写。任何内部缓存的数据都被视为可疑数据,并受 在使用之前对数据库文件进行验证。其他 进程可以读取或写入数据库作为自己的锁定状态 许可证。这是默认状态。
共享可以读取数据库,但不能写入数据库。任意数量的 进程可以同时持有 SHARED 锁,因此可以有 许多同时阅读器。但不允许使用其他线程或进程 在一个或多个 SHARED 锁处于活动状态时写入数据库文件。
保留RESERVED 锁表示进程正计划写入 数据库文件,但它目前只是 从文件中读取。一个只能有一个 RESERVED 锁处于活动状态 时间,但多个 SHARED 锁可以与单个 RESERVED 锁共存。 RESERVED 与 PENDING 的不同之处在于可以获取新的 SHARED 锁 而有一个 RESERVED 锁。
待定PENDING 锁表示持有该锁的进程想要写入 尽快到数据库,只是在等待所有当前 要清除的 SHARED 锁,以便它可以获得 EXCLUSIVE 锁。没有新的 如果出现以下情况,则允许对数据库使用 SHARED 锁 PENDING 锁处于活动状态,但允许现有 SHARED 锁 继续。
独家需要 EXCLUSIVE 锁才能写入数据库文件。 文件上只允许有一个 EXCLUSIVE 锁,不允许使用其他锁 任何种类都允许与 EXCLUSIVE 锁共存。为了 最大化并发性,SQLite 致力于最大限度地减少 持有独家锁。

操作系统接口层理解并跟踪所有五个 如上所述的锁定状态。 页面模块仅跟踪五种锁定状态中的四种。 PENDING 锁始终只是临时锁 通往 EXCLUSIVE 锁的垫脚石,因此页面模块 不跟踪 PENDING 锁。

4.0 回滚日志

当进程想要更改数据库文件时(但事实并非如此) 在 WAL 模式下),它 首先记录原始未更改的数据库内容 在回滚日志中。回滚日志是普通的 始终位于的磁盘文件 在与数据库文件相同的目录或文件夹中,并具有 与数据库文件同名,但添加了 -journal 后缀。回滚日志还记录初始 数据库的大小,以便在数据库文件增长时可以截断它 回滚时恢复到其原始大小。

如果SQLite同时使用多个数据库 (使用 ATTACH 命令)则每个数据库都有自己的回滚日志。 但还有一个单独的聚合日志称为超级期刊。 超级日志不包含用于回滚的页面数据变化。取而代之的是,超级期刊包含每个ATTACHed数据库的单独数据库回滚日志。 每个单独的数据库回滚日志还包含名称 的超级期刊。 如果没有ATTACHed数据库(或者没有ATTACHed 数据库) 正在参与当前交易)没有超级期刊是已创建,并且正常回滚日志包含空字符串在通常保留用于记录名称的地方 超级期刊。

如果回滚日志需要回滚,则称其为热回滚 为了恢复其数据库的完整性。 当进程位于数据库中间时,将创建热日志 更新和程序或操作系统崩溃或电源故障可防止 从完成开始的更新。 热日志是一种例外情况。 存在热日志以从崩溃和电源故障中恢复。 如果一切正常 (也就是说,如果没有崩溃或电源故障) 你永远不会得到一本热门的日记。

如果不涉及超级期刊,则 如果日记存在并且具有非零标题,则该日记为热 及其对应的数据库文件 没有 RESERVED 锁。 如果在文件日记中命名了超级日志,则文件日志 如果它的超级日志存在并且没有 RESERVED 锁定相应的数据库文件。 了解期刊何时热门很重要,因此 前面的规则将在项目符号中重复:

  • 如果...
    • 它存在,并且
    • 其大小大于 512 字节,并且
    • 日志标题为非零且格式正确,并且
    • 它的超级期刊存在,或者超级期刊名称是 空字符串,以及
    • 相应的数据库文件上没有 RESERVED 锁。

4.1 处理热点期刊

在从数据库文件读取之前,SQLite始终会检查是否 数据库文件具有热日志。如果文件确实有热日志,则 在读取文件之前回滚日志。通过这种方式,我们确保 数据库文件在读取之前处于一致状态。

当进程想要从数据库文件中读取时,它遵循 以下步骤顺序:

  1. 打开数据库文件并获取 SHARED 锁。如果 SHARED 锁 无法获取,立即失败并返回SQLITE_BUSY。
  2. 检查数据库文件是否具有热日志。如果文件 没有热日记,我们就完了。立即返回。 如果存在热日记帐,则必须回滚该日记帐 此算法的后续步骤。
  3. 获取数据库文件的 PENDING 锁,然后获取 EXCLUSIVE 锁。 (注意:不要获取 RESERVED 锁,因为这会使 其他进程认为期刊不再热门。如果我们 未能获得这些锁意味着另一个过程 已经在尝试进行回滚。在这种情况下, 删除所有锁,关闭数据库,然后返回SQLITE_BUSY。
  4. 读取日志文件并回滚更改。
  5. 等待回滚的更改被写入 持久性存储。这样可以保护数据库的完整性 以防再次发生电源故障或崩溃。
  6. 删除日志文件(或将日志截断为零字节 如果 PRAGMA journal_mode=TRUNCATE 为 设置,如果设置了 PRAGMA journal_mode=PERSIST),则将日志标题归零)。
  7. 如果安全,请删除超级日志文件。 此步骤是可选的。它在这里只是为了防止陈旧 磁盘驱动器杂乱无章的超级日志。 有关详细信息,请参阅下面的讨论。
  8. 删除 EXCLUSIVE 和 PENDING 锁,但保留 SHARED 锁。

上述算法成功完成后,可以安全地 从数据库文件中读取。完成所有读取后, SHARED 锁被丢弃。

4.2 删除过时的超级日志

过时的超级日志是不再存在的超级日志用于任何事情。没有要求过时的超级日志被删除。这样做的唯一原因是释放磁盘空间。

如果没有单个文件日志指向,则超级日志已过时到它。为了弄清楚超级日志是否过时,我们首先阅读 super-journal,以获取其所有文件日志的名称。然后 我们检查每个文件日志。如果任何文件日志命名为在超级日志中存在并指向超级日志,那么超级日志并没有过时。如果所有文件日志都丢失 或参考其他超级日志或根本没有超级日志,则 我们正在测试的超级日志已经过时,可以安全地删除。

5.0 写入数据库文件

要写入数据库,进程必须首先获取 SHARED 锁 如上所述(如果有,可能会回滚不完整的更改 是一本热门期刊)。 获取 SHARED 锁后,必须获取 RESERVED 锁。 RESERVED 锁表示进程打算写入 数据库在将来的某个时候。一次只能处理一个进程 可以持有 RESERVED 锁。但其他进程可以继续读取 数据库,而保留 RESERVED 锁。

如果要写入的进程无法获取 RESERVED lock,这必须意味着另一个进程已经具有 RESERVED 锁。 在这种情况下,写入尝试将失败并返回SQLITE_BUSY。

获取RESERVED锁后,想要写入的进程创建回滚日志。日志的标题已初始化替换为数据库文件的原始大小。日记帐标题中的空格也保留给超级期刊名称,尽管超级期刊name最初为空。

在对数据库的任何页面进行更改之前,该过程会写入将该页面的原始内容添加到回滚日志中。变化 “到”页首先保存在内存中,不会写入磁盘。 原始数据库文件保持不变,这意味着其他 进程可以继续读取数据库。

最终,写入过程将需要更新数据库文件,要么是因为它的内存缓存已满,要么是因为它是准备提交其更改。在此之前,编写器必须确保没有其他进程正在读取数据库,并且回滚日志数据安全地位于磁盘表面,以便可用于回滚 电源故障时更改不完整。 步骤如下:

  1. 确保所有回滚日志数据实际上都已写入磁盘的表面(而不仅仅是保持在操作中系统或磁盘控制器缓存),以便在发生电源故障时电源恢复后,数据仍将存在。
  2. 获取数据库文件的PENDING锁和EXCLUSIVE锁。 如果其他进程仍然具有SHARED锁,则编写器可能具有等到这些 SHARED 锁清除后才能获得一个 EXCLUSIVE锁。
  3. 将当前保存在内存中的所有页面修改写入原始数据库磁盘文件。

如果写入数据库文件的原因是因为内存缓存已满,则编写器不会立即提交。相反作者可能会继续对其他页面进行更改。以前后续更改将写入数据库文件,即回滚日志必须再次刷新到磁盘。另请注意,EXCLUSIVE写入器最初为了写入数据库而获取的锁必须保留,直到提交所有更改。这意味着没有其他进程能够从 内存缓存首次溢出到磁盘的时间,直到事务发生 提交。

当编写器准备好提交其更改时,它会执行以下命令 步骤:

  1. 获取数据库文件的 EXCLUSIVE 锁,并获取确保所有内存更改都已写入数据库文件使用上述步骤 1-3 的算法。
  2. 将所有数据库文件更改刷新到磁盘。等待这些更改 实际写入磁盘表面。
  3. 删除日志文件。(或者,如果 PRAGMA journal_mode是 TRUNCATE 或 PERSIST,截断日志文件或将日志文件的标题归零, 分别。这是变化的那一刻 承诺。在删除日志文件之前,如果发生电源故障 或者发生崩溃,下一个打开数据库的进程将看到 它有一个热日志,并将回滚更改。 删除日记后,将不再有热日记 这些变化将持续下去。
  4. 从数据库文件中删除 EXCLUSIVE 和 PENDING 锁。

一旦从数据库文件中释放 PENDING 锁,其他 进程可以再次开始读取数据库。在当前的实现中, RESERVED 锁也会被释放,但这不是必需的 正确操作。

如果一个事务涉及多个数据库,那么一个更复杂的 使用提交序列,如下所示:

  1. 确保所有单独的数据库文件都具有 EXCLUSIVE 锁和 有效日记帐。
  2. 创建超级日记帐。超级期刊的名称是任意的。 (当前实现将随机后缀附加到 main 数据库文件,直到它找到以前不存在的名称。 用所有单个期刊的名称填充超级期刊 并将其内容刷新到磁盘。
  3. 将超级期刊的名称写入所有单独的期刊(在为此目的预留的空间中 各个日志的标题)并刷新 将单个日志磁盘并等待这些更改到达 磁盘表面。
  4. 将所有数据库文件更改刷新到磁盘。等待这些更改 实际写入磁盘表面。
  5. 删除超级日志文件。这是变化的那一刻 承诺。在删除超级日志文件之前,如果电源故障 或发生崩溃,则单个文件日志将被视为热 并将在下一个进程中回滚 尝试阅读它们。删除超级日志后, 文件日志将不再被视为热门,并且更改 会持续存在。
  6. 删除所有单独的日记帐文件。
  7. 从所有数据库文件中删除 EXCLUSIVE 和 PENDING 锁。

5.1 写入低效冲突

在 SQLite 版本 2 中,如果许多进程正在从数据库中读取, 可能从来没有一个时候没有活跃的读者。如果 数据库,则任何进程都无法对数据库进行更改 因为不可能获得写锁。这种情况 被称为作家饥饿

SQLite 版本 3 旨在通过使用 PENDING 锁。PENDING 锁允许现有读卡器继续 但会阻止新读取器连接到数据库。因此,当 进程想要写一个繁忙的数据库,它可以设置一个 PENDING 锁 将阻止新读者进入。假设现有读者这样做 最终完成,所有共享锁最终将清除,并且 作者将有机会进行更改。

6.0 如何损坏数据库文件

寻呼机模块非常强大,但它可以被颠覆。 本节试图识别和解释风险。 (另请参阅本文的“可能出错的事情”部分 在 Atomic Commit 上。

显然,引入错误数据的硬件或操作系统故障 进入数据库文件或日志的中间会引起问题。 同样 如果恶意进程打开数据库文件或日志并写入格式不正确的文件 数据进入其中,那么数据库就会损坏。 对于这类问题,我们无能为力 所以他们没有得到进一步的关注。

SQLite 使用 POSIX 咨询锁在 Unix 上实现锁定。上 Windows 它使用 LockFile()、LockFileEx() 和 UnlockFile() 系统 调用。SQLite 假定这些系统调用的所有工作都按通告的方式进行。如果 事实并非如此,则可能导致数据库损坏。一个人应该 请注意,已知 POSIX 咨询锁定存在错误,甚至未实现 在许多 NFS 实现(包括最新版本的 Mac OS X)上 并且有关于锁定问题的报告 适用于 Windows 下的网络文件系统。你最好的防御就是不要 对网络文件系统上的文件使用 SQLite。

SQLite 使用 fsync() 系统调用将数据刷新到 Unix 下的磁盘,并且 它使用 FlushFileBuffers() 在 Windows 下执行相同的操作。再来一次 SQLite 假定这些操作系统服务按通告的方式运行。 但据报道,fsync() 和 FlushFileBuffers() 并不总是 正常工作,尤其是对于某些网络文件系统或廉价的 IDE 磁盘。 显然,一些IDE磁盘制造商的控制器芯片报告 该数据已到达磁盘表面,而实际上数据仍在 在磁盘驱动器电子设备中的易失性缓存内存中。还有 报告 Windows 有时会选择忽略 FlushFileBuffers() 原因不明。作者无法核实任何这些报告。 但如果它们是真的,那就意味着数据库损坏是可能的 意外断电后。这些是硬件和/或操作 SQLite无法防御的系统错误。

如果挂载的 Linux ext3 文件系统没有 “barrier=1” 选项 在 /etc/fstab 中,磁盘驱动器已启用写入缓存 那么文件系统损坏可能会在断电或操作系统崩溃后发生。 是否发生损坏取决于磁盘控制的详细信息 硬件;使用廉价的消费级磁盘时,损坏的可能性更大 对于具有高级的企业级存储设备来说,问题更少 非易失性写入缓存等功能。 各种 ext3 专家证实了这种行为。 我们被告知大多数 Linux 发行版不使用 barrier=1 并且使用 不禁用写缓存,所以大多数 Linux 发行版容易受到此问题的影响。请注意,这是一个 操作系统和硬件问题,并且没有SQLite的内容 可以做来解决它。 其他数据库引擎也遇到了同样的问题。

如果发生崩溃或电源故障并导致日志过热,但 日志被删除,下一进程打开数据库不会 知道它包含需要回滚的更改。回滚 不会发生,并且数据库将处于不一致状态。 回滚日志可能因多种原因而被删除:

  • 管理员可能在操作系统崩溃或电源故障后进行清理, 查看日志文件,认为它是垃圾文件,然后将其删除。
  • 某人(或某个进程)可能会重命名数据库文件,但无法重命名 同时重命名其关联的日记帐。
  • 如果数据库文件具有别名(硬链接或软链接)和文件 由与用于创建日记帐的别名不同的别名打开, 则找不到日记帐。若要避免此问题,应 不创建指向 SQLite 数据库文件的链接。
  • 电源故障后的文件系统损坏可能会导致 要重命名或删除的日志。

上面的最后一个(第四个)项目符号值得补充评论。当 SQLite 创建时 Unix 上的日志文件,它会打开包含该文件的目录,然后 在目录上调用 fsync(),以推送目录信息 到磁盘。但是假设其他一些进程正在添加或删除不相关的过程 文件添加到包含数据库和日志的目录中 停电的时刻。这个其他人的所谓不相关的行为 进程可能会导致日志文件从目录中删除,并且 移至“失物招领”。这种情况不太可能发生,但可能会发生。 最好的防御措施是使用日志文件系统或保留 数据库和日志单独放在一个目录中。

对于涉及多个数据库和超级日志的提交,如果 不同的数据库位于不同的磁盘卷上,并且发生电源故障 在提交期间,当计算机恢复时,磁盘可能会 以不同的名称重新装裱。或者某些磁盘可能未装载 完全。发生这种情况时,各个文件日志和 超级期刊可能无法找到对方。最坏的结果来自 这种情况是提交不再是原子的。 某些数据库可能会回滚,而其他数据库可能不会。 所有数据库将继续自洽。 若要防止此问题,请保留所有数据库 在同一磁盘卷上和/或使用完全相同的名称重新装载磁盘 停电后。

7.0 SQL 级别的事务控制

SQLite 版本 3 中对锁定和并发控制的更改也 在 SQL 中引入事务工作方式的一些细微变化 语言水平。 默认情况下,SQLite 版本 3 在自动提交模式下运行。 在自动提交模式下, 对数据库的所有更改都会在关联的所有操作后立即提交 当前数据库连接完成。

SQL 命令“BEGIN TRANSACTION”(TRANSACTION 关键字 是可选的)用于将 SQLite 从自动提交模式中取出。 请注意,BEGIN 命令不会获取数据库上的任何锁。 在 BEGIN 命令之后,当第一个 执行 SELECT 语句。在以下情况下将获得 RESERVED 锁 执行第一个 INSERT、UPDATE 或 DELETE 语句。无独家 锁定,直到内存缓存填满,并且必须 溢出到磁盘或直到事务提交。这样, 系统延迟阻止对文件的读取访问,直到 最后可能的时刻。

SQL 命令“COMMIT”实际上不会提交对 磁盘。它只是重新打开自动提交。然后,在 命令,常规自动提交逻辑接管并导致 实际提交到磁盘。 SQL 命令“ROLLBACK”也通过重新打开自动提交来运行, 但它也设置了一个标志,告诉自动提交逻辑回滚 而不是提交。

如果 SQL COMMIT 命令打开自动提交,并且自动提交逻辑 然后尝试提交更改,但失败,因为其他进程正在保留 一个 SHARED 锁,然后自动关闭自动提交。这 允许用户在 SHARED 锁之后稍后重试 COMMIT 本来有机会通关的。

如果对同一个 SQLite 数据库执行多个命令 连接时,自动提交被推迟到非常 最后一个命令完成。例如,如果 SELECT 语句正在 执行后,命令的执行将暂停,因为 返回结果。在此暂停期间,其他 INSERT、UPDATE 或 DELETE 可以对数据库中的其他表执行命令。但没有 这些更改将提交,直到原始 SELECT 语句完成。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【蓝桥杯嵌入式】六、真题演练(一)-1演练篇:第 届真题

温馨提示: 真题演练分为模拟篇和研究篇。本专栏的主要作用是记录我的备赛过程,我打算先自己做一遍,把遇到的问题和不同之处记录到演练篇,然后再返回来仔细研究一下,找到最佳的解题方法记录到研究篇。 解题记录&#x…

Yarn的安装及使用(1):安装

一、Yarn的安装 在不同操作系统上安装Yarn的步骤和注意事项: 1、Windows 1.1 通过.msi安装程序安装: 步骤: 访问 Yarn官方网站 下载适用于Windows的.msi安装包。 运行下载好的.msi文件,按照向导进行安装。 在安装过程中&#…

Apache Hive的基本使用语法(一)

一、数据库操作 创建数据库 create database if not exists myhive;查看数据库 use myhive; desc database myhive;创建数据库并指定hdfs存储 create database myhive2 location /myhive2;删除空数据库(如果有表会报错) drop database myhive;…

爱上数据结构:栈和队列的概念及使用

​ ​ 🔥个人主页:guoguoqiang. 🔥专栏:数据结构 ​ 一、栈 1.栈的基本概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端 称为栈顶,…

酒店管理系统项目用例图及用例说明

1、系统功能模块图 2、部分系统功能模块说明 (1)查询房间剩余 模块名称:管理员登录 编号:1-1 主要功能:验证管理员登录用户名及密码 上级调用模块:无 下级调用模块: 约束: &a…

强化基础-Java-泛型基础

什么是泛型? 泛型其实就参数化类型,也就是说这个类型类似一个变量是可变的。 为什么会有泛型? 在没有泛型之前,java中是通过Object来实现泛型的功能。但是这样做有下面两个缺陷: 1 获取值的时候必须进行强转 2 没有…

音视频开发之旅(80)- AI数字人-腾讯开源AniPortrait-音频驱动的肖像动画

目录 1、前言 2、效果展示 3、原理学习 4、遇到的问题与解决方案 5、资料 一、前言 一个月前阿里Emo发布,通过音频驱动的非常自然的肖像视频,引起很大反响。具体看下面的视频,但是并没有开源其代码。 这两天腾讯开源了其音频驱动的肖像…

2024年美团笔试题(1)

一.题目描述 小美拿到了一个排列,其中初始所有元素都是红色,但有些元素被染成了白色。 小美每次操作可以选择交换任意两个红色元素的位置。她希望操作尽可能少的次数使得数组变成非降序,你能帮帮她吗? 排列是指:一个长度为n的数组&#…

Java | Leetcode Java题解之第1题两数之和

题目&#xff1a; 题解&#xff1a; class Solution {public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map new HashMap<>();for(int i 0; i< nums.length; i) {if(map.containsKey(target - nums[i])) {return new int[] {map.get(tar…

【React】vite + react 项目,进行配置 eslint

安装与配置 eslint 1 安装 eslint babel/eslint-parser2 初始化配置 eslint3 安装 vite-plugin-eslint4 配置 vite.config.js 文件5 修改 eslint 默认配置 1 安装 eslint babel/eslint-parser npm i -D eslint babel/eslint-parser2 初始化配置 eslint npx eslint --init相关…

应急物资管理系统|实现应急物资的全生命周期管理和监控

应急物资管理系统是一种现代化、智能化、可视化的物资管理平台&#xff0c;主要用于实现对应急物资的全生命周期管理和监控&#xff0c;并提供可靠的应急响应支持。 应急物资管理系统功能 准入控制&#xff1a;东识应急物资管理系统可以实现准入控制&#xff0c;确保只有经过授…

C语言----strcmp()函数:比较两个字符串

C语言中strcmp&#xff08;&#xff09;用于对两个字符串进行比较&#xff08;区分大小&#xff09;。 头文件&#xff1a;string.h 语法原型 int strcmp(const char*str1,const char*str2) 参数str1和str2是参与比较的两个字符串。 strcmp()是根据ASCLL编码依次比较str1和str…

MP设置动态表名

Mybatis设置动态表名 Mybatis设置动态表名1.动态表名插件2.传递表名3.注意事项 Mybatis设置动态表名 1.动态表名插件 MybatisPlus中提供了一个动态表名的插件&#xff1a;https://baomidou.com/pages/2a45ff/#dynamictablenameinnerinterceptor 插件的部分源码如下&#xff…

大模型面试准备(十):大模型数据处理方法及优秀的开源数据介绍

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

【Consul】Linux安装Consul保姆级教程

【Consul】Linux安装Consul保姆级教程 大家好 我是寸铁&#x1f44a; 总结了一篇【Consul】Linux安装Consul保姆级教程✨ 喜欢的小伙伴可以点点关注 &#x1f49d; 前言 今天要把编写的go程序放到linux上进行测试Consul服务注册与发现&#xff0c;那怎么样才能实现这一过程&am…

内网渗透之域环境探索和简单提权

参考文章&#xff1a;http://t.csdnimg.cn/AZ2OR 一个简单的域环境可以这样子搭建&#xff1a; 其中边界服务器有两张网卡&#xff0c;一个是对外的公网网卡&#xff0c;另一张是对内的局域网网卡。一般渗透过程中&#xff0c;拿下这个作为跳板机&#xff0c;进而继续渗透。 …

P23—P25:标识符和关键字

标识符 什么是标识符&#xff1f; 在java源程序中&#xff0c;程序员有权自己命名的单词都是标识符在EditPlus编译器中&#xff0c;表示符以黑色高亮字体显示 标识符可以标识什么元素&#xff1f; 类名方法名变量名接口名常量名 … 标识符的命名规则&#xff1a; 只能由**数…

C++学习随笔(8)——模板初阶

本章我们来学习一下C的模版部分&#xff01; 目录 1. 泛型编程 2. 函数模板 2.1 函数模板概念 2.1 函数模板格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.5 模板参数的匹配原则 3. 类模板 3.1 类模板的定义格式 3.2 类模板的实例化 1. 泛型编程 如何实现一个通…

Android vehicle车辆属性新增demo

目录 前言一、Vehicle模块1.1 简介1.2 Vehicle框架1.3 主要功能和特点1.4 重要服务CarService1.4.1 简介1.4.2 组成1.4.3 启动时序1.4.4 作用 二、车辆属性新增demo2.1 CarPropertyService2.1.1 简介2.1.2 架构2.1.3 车辆属性 API2.1.4 CarPropertyService 初始化流程 2.2 App …

鸿蒙ARKTS--简易的购物网站

目录 一、media 二、string.json文件 三、pages 3.1 登录页面&#xff1a;gouwuPage.ets 3.2 PageResource.ets 3.3 商品页面&#xff1a;shangpinPage.ets 3.4 我的页面&#xff1a;wodePage.ets 3.5 注册页面&#xff1a;zhucePage.ets 3. 购物网站主页面&#xff…