InnoDB Data Locking - Part 2 “Locks“

什么是数据库“锁”?

当我熟悉数据库术语时,我发现非常困惑的一件事是“锁【lock】”这个词在数据库中的含义与在编程中的含义不同。


在编程中,如果你有一个“锁”,那么它就是内存中存储在某个地址下的单个对象,然后有多个线程尝试“锁定【locking】”它,要么成功,要么等待直到成功。 因此,每个资源都有一个锁,而“锁定【locking】”操作是线程执行的操作,您可以使用调试器【debugger】捕获它发生的那一刻,但是没有内存对象(除了调用堆栈外)显式地记录给定线程尝试或成功获取锁的事实。


在 InnoDB 中,上述概念被称为“锁存器【latch】”,将“锁【lock】”一词重新定义为完全不同的东西。 在 InnoDB 的锁系统中,“锁”实际上更像是“特定事务【transaction】对特定资源【resource】的特定类型的访问权【access right】的请求”。 因此,对于某一特定资源,如果有多个事务请求访问该资源,则可能存在数百个“锁【lock】”;如果单个事务需要使用不同的锁定模式【lock modes】访问该资源,则甚至可能会存在多个“锁【lock】”。 “锁【lock】”可以处于等待状态,也可以被授予并记录给定事务对给定资源的访问权【access right】。 你可以把它想象成一张纸质表格,你必须提交申请才能获得某件事的许可,在某个官员的抽屉里等待批准盖章,最终获得批准,并作为证明你的权利的证书。 因此,锁更像是记录请求状态的元组:

<who?, what?, how?, granted?>

例如(大大简化)锁系统可以同时包含以下对单个资源(即 report 表中的 row#2 资源)相关的锁: 

<transaction#3305, row#2 of table `report`, shared, granted >
<transaction#3305, row#2 of table `report`, exclusive, granted >
<transaction#3306, row#2 of table `report`, exclusive, waiting >

显式地建模谁(who)请求什么(what),并将其作为内存中的对象的好处之一是您可以通过查看这些对象来检查情况。 特别是,您可以查询 performance_schema.data_locks 表来查看 InnoDB 引擎中的活动事务创建的所有锁:

我稍后将在本文中的“记录锁【Record locks】”部分解释 LOCK_MODE 列中所有可能值的确切含义,现在只要有一个直觉就足够了,即(粗略地说)S 和 X 分别对应于共享和独占。

注: 如果您开始怀疑在另一个表中保留锁来保护对表的访问的悖论,让我安慰你:这不是一个真正的 InnoDB 表。有一些魔法使它看起来像一个表,但它实际上是扫描服务器内存中的实际的低级数据结构【low-level data structures】并将它们呈现为整齐的行的结果。

实际上,这些只是显式锁【explicit locks】——出于性能原因,InnoDB 尝试避免显式表示访问权【access rights】,因为它可以从行本身的状态【state】中隐式推断出访问权【access rights】。 您可以看到,每次事务修改一行【row】时,它都会将自己的 id 放在该行的 header 中,以表明它是最后一个修改该行的人 —— 如果这个事务仍然没有提交,那么它就意味着它仍然拥有对该记录的独占访问权(它也必须拥有它才能修改行,并且“两阶段锁定”中的锁仅在提交时释放),而不需要浪费空间来显式存储此信息。 此类隐式锁不会出现在 performance_schema.data_locks 中(这需要扫描撤消日志【undo logs】以识别所有隐式锁【implicit locks】)。 创建隐式锁的最常见原因是针对  INSERT 操作:在插入事务提交之前,成功插入的行对其他事务是不可见的,并且单个事务插入多行是常见情况,因此不为新插入的行创建显式锁的成本更低,而只是隐式地假设插入事务对所有这些行具有独占访问权,因为它的事务 id 写在这些行的 header 中。 正如下一章节第 3 部分“死锁”中将解释的,正确地建模和监视谁(who)等待谁(who)非常重要,因此每当锁系统识别出隐式锁可能是另一个事务必须等待的原因时,它就会将隐式锁转换为显式锁,以便可以正确地分析、监视、报告等。这被称为隐式到显式的转换,并且在语义上不会改变任何东西——它只是改变了锁的表示。

表锁【table lock】


如前所述,在 InnoDB 中,大部分锁定发生在行【row】的粒度上。 这增加了并行性的机会,因为多个事务可以同时处理不相交的行【rows】集,而服务器仍然可以假装一个事务在另一个事务之后以可序列化的顺序发生。 还有表级锁,它可以让您锁定整个表。 由于 InnoDB 与 Server 集成的方式,这是相当罕见的。 InnoDB 位于 Server 下方,Server 也有自己的锁定机制,因此大多数时候 InnoDB 甚至不知道事务已经锁定了一个表,因为它发生在“上面”。 坦率地说,如果我们现在谈论表锁,我有点纠结:从某种意义上说,它们比记录锁【Record lock】简单得多,另一方面,InnoDB 和 Server 协调对表【table】的访问的方式,各自都试图以自己的方式来做,使对所发生事情的理解变得更加复杂。 特别地是,这意味着 performance_schema.data_locks 不会报告由 Server 本身维护的锁。 因此,在默认配置下,您会看到一些令人困惑的事情发生, 例如:

您可能期望您的事务已锁定表 t,但您看不到任何锁:

con2> SELECT * FROM performance_schema.data_locks;

Empty set (0.00 sec)

 而且你甚至看不到事物!

con2> SELECT * FROM information_schema.innodb_trx;

Empty set (0.00 sec)

这是因为默认情况下,Server 和 InnoDB 的配置方式是:如果您执行 LOCK TABLES, Server 将提交【commit】当前事务。 事实上,即使我们自己没有发出 COMMIT 指令,任何其他客户端都已经可以看到我们刚刚插入的行,这意味着事务被认为已经提交(哎呀!):

“LOCK TABLES 机制”与“事务机制”有些不同,其默认行为是在开始处理另一个之前要先完成当前这个。 您可以将 LOCK TABLES + UNLOCK TABLES 视为临界区,并且您可以以同样的方式思考 BEGIN + COMMIT 。 但是,默认情况下你不能将两者交错。

您可以通过查询一个完全不同的名为 performance_schema.metadata_locks 的表来验证 LOCK TABLES t READ 是否有效(请注意名称中的“meta”):

MySQL 的架构是 Server 和 InnoDB 是完全独立的,我不想假装我对 Server 的内部结构了解很多。 所以,我只想说这个表显示了 Server 所获取的锁,并且它们确实阻止了其他客户端尝试修改该表:

con3> insert into test.t values (10);

将会等待,您可以通过以下方式验证:

但请注意,这与 InnoDB 的锁系统无关:实际上 InnoDB 目前没有正在进行的事务:

on2> SELECT * FROM information_schema.innodb_trx;

Empty set (0.00 sec)

 一旦你试图在 con1 中启动一个执行 LOCK TABLES 的事务…

con1> BEGIN;

Query OK, 0 rows affected (0.00 sec)

con3 中的插入将继续并成功:

con3>  insert into test.t values (10);

Query OK, 1 row affected (3 min 19.60 sec)

(这 3 分钟是我在 con3 中输入  INSERT  后,到在 con1 中输入 BEGIN 所花费的时间)

因此,看起来使用 BEGIN 启动事务会隐式  UNLOCK TABLES。 事实上:默认情况下,如果您开始处理事务,那么您就会结束锁定表【locking tables】。

这里还要注意的另一件事是,con3 在发出  INSERT  之前不必使用任何 LOCK TABLES 语句,但在 con1 释放表之前阻止 con3 操作的机制是有效的。 这意味着参与这种 Servel 级别的表锁定机制【Servel-level table locking mechanism】是强制性的和隐式的,而不是您必须选择加入并且可能会错过的事情。 我们说这种锁定是强制性的,而不是建议性的。

另外,请注意, INSERT  语句所需的锁类型是 SHARED_WRITE ,这可能听起来令人困惑,因为到目前为止我们通常将“shared”等同于“reading”,将“exclusive”等同于“write”。 这里正确的解释是,在同一张表中可能有多个事务在编辑行。 因此,他们可以彼此共享对表的访问,即使他们每个人都想写入,只要他们写入不同的行即可。 因此它同时是“(在表级别)shared”和“(在行级别)write”。

但是, SHARED_WRITE  与  SHARED_READ_ONLY 冲突,这也是有道理的,因为 con1 希望阻止对整个表的任何写入。 这样的 SHARED_READ_ONLY 在名称中带有“shared”,因为它可以与其他也需要 SHARED_READ_ONLY 的事务兼容,因为它们的利益一致:它们都希望防止修改。

InnoDB 里的表锁 (hopefully less confusing now!)

好的,以上讨论的这些是由 Server 维护的锁,但是本系列博客文章的目的是讨论 InnoDB 的锁系统。 我们如何在 InnoDB 中创建表级锁?

官方文档中给出的技巧是禁止使用 BEGIN(及其同义的 START TRANSACTION ),这会隐式导致 UNLOCK TABLES。 相反,我们将禁用自动提交【auto commit】,以便隐式地表明我们所做的一切都是事务的一部分。 我们将处于事务内部,而无需显式启动它。太酷辣~

所以,我们现在得到了我们想要的:一个活跃的 InnoDB 事务(InnoDB 中的 ID 为 3851),它拥有 InnoDB 内的显式表锁,对应于相应的 Server 线程(ID 为 49)所持有的锁。 是的,表被锁定两次:在 Server 级别和 InnoDB 级别:

tablelock held by Server layerlock held inside InnoDB engine
tSHARED_READ_ONLYS
t1SHARED_NO_READ_WRITEX

InnoDB 里的表意图锁【Table Intention locks】 

在 InnoDB 中获取表锁的另一种方式是,当您尝试读取或修改表的某个部分时,也就是当您尝试 SELECT 一行、UPDATE 现有行或 INSERT 新行时,这种情况经常发生,并且不需要任何 LOCK TABLES 或 autocommit 技巧。

例如,假设我们启动一个全新的事务,并插入一个新行:

为了能够尝试向表 t 插入任何内容,该事务将需要获得对表的特定权限:

InnoDB 的  IX  对应于 Server 的  SHARED_WRITE ,我们之前看到过。为了继续这个例子,让我们假设这个事务从 t1 执行读取:

令人惊讶的是,在这种情况下,InnoDB 没有获取表级锁。这是有道理的:行也没有被锁定,因为它是一个非锁定选择【on-locking select】,并且查询【query】在 Server 级别受到保护:

如果您尝试通过执行锁定选择【locking select】(SELECT ... FOR SHARE / UPDATE)来锁定表的一部分以进行读取,则行为会有所不同,例如: 

这一次,当我们试图尝试读取并锁定表 t1 的一部分时,我们为它请求 IS。

这里出现的一件事是,当我们尝试在表级别指定所需的访问权限时,“整个表【whole table】”和“部分表【part of the table】”之间存在区别。您可以想象以下组合:

  • X → I want to be the only one who has access to the whole table
  • S → I want to be able assume that whole table is protected from modification
  • IX → I intend to modify some part of the table
  • IS → I intend to read some part of the table

 (这些名称((X, S, IX, IS)是InnoDB谈论表锁的方式)

让我们花一点时间来弄清楚哪些锁请求是相互兼容的,哪些是不能同时授予的,就好像我们要自己设计一样。这种访问权限之间的兼容性关系可以巧妙地总结为一个兼容性矩阵,该矩阵有一行代表您可能想要请求的每种可能的访问权限,还有一列代表另一个事务已经拥有的每种可能的访问权限:

↓my request \ held by other→XSIXISAUTO_INC
X?????
S?????
IX?????
IS?????
AUTO_INC?????

让我们弄清楚如何在上面的矩阵中使用⌛(新请求必须等待)和 ✅(新请求可以继续)。

显然,X 似乎与其他任何东西都不兼容。S 似乎与其他 S 和 IS 均兼容,但它无法应对另一个线程对表的一小部分进行的修改,因此它与 IX 冲突。

↓my request \ held by other→XSIXISAUTO_INC
X
S?
IX???
IS???
AUTO_INC????

IX 是否应与其他 IX 或 IS 冲突?不——拥有这样一个细粒度系统的全部意义在于允许对表进行并发修改。当然,我们必须以某种方式确保两个事务不会修改冲突的行集【set of rows】,但这可以在较低粒度级别上处理,即当它们尝试请求访问单个行时。请求 IX 的事务所要求的只是“请求将来访问行的许可/权限”。这种“请求许可/权限”可能听起来很愚蠢,但它至少有两个目的: 

  • 我们可以在事务开始搜索要访问的实际行【row】之前快速响应“不行,你的 IS 必须等待,因为有人用 X 锁定了整个表”,从而为所有人省去麻烦。
  • 授予 IS 或 IX 锁是一个明确的信号,表明表内正在进行工作,任何其他试图锁定整个表的事务都必须考虑到这一点,因此它可能必须等到它们完成为止(“危险,下面的工人!”)

可以想象一种不同的设计,其中不存在意向锁(IS 和 IX),每次事务尝试锁定单个行时,它必须首先检查是否存在冲突的 S 或 X 表锁,每次事务尝试 X 或 S 锁定表时,它必须首先检查是否存在任何冲突的记录级锁【record-level locks】。预先指定意图的一个好处是,它通常会减少死锁(或更快地暴露它们)。另一个好处是,如果您仔细考虑“首先检查是否存在现有记录级锁”的设计,您会意识到您可能希望缓存此问题的答案,以避免昂贵的查找,尽量减少更新此信息的同步工作,并采用某种合理的方式报告正在发生的事情……最终您将得到一些相当于 IS 和 IX 锁的东西。

因此,我们最终得到以下兼容性矩阵:

↓my request \ held by other→XSIXISAUTO_INC
X
S
IX
IS
AUTO_INC

(我已将尚未提及的  AUTO_INC  锁放入此矩阵中,以使其完整,以供将来参考。我希望您现在有足够的直觉来自己弄清楚为什么  AUTO_INC  锁必须与 S 冲突,以及为什么它与 IX 略有不同,因为它与自身冲突。)

剧透:
当在表的末尾插入一行并通过 AUTO INCREMENT 为其分配主键时,就会使用 AUTO_INC,因此,自然必须注意同步两个并行执行此操作的事务,这样它们就不会以相同的键结束。

请注意,这个矩阵具有对称性这一良好特性:如果 A 与 B 冲突,则 B 也与 A 冲突。在处理记录级锁【record-level locks】时,我们将看到没有此特性的矩阵,您将学会体会到能够使用对称冲突关系并漫不经心地说出“A 和 B 相互冲突”之类的话而不指定方向是多么令人欣慰。

看待表锁的另一种视角是将其概括为嵌套作用域【nested scope】的任意层次结构(例如:数据中心【datacenter】 > 数据库【database】 > 表【table】 > 分区【partition】 > 索引【index】 > 行【row】 > 字段【foeld】),并尝试找出一种系统,在该系统中,您可以以这样的方式锁定任何这些作用域【scope】,以便发现冲突。比如说,我想删除一个分区【partition】,而其他人正在尝试对整个数据库进行快照?如何对其进行建模以跟踪正在发生的事情并确定是否有人应该等待?我们的想法是允许人们在给定的较低级别请求 X 或 S 锁,前提是他们已经获得了所有以上级别的 IX 或 IS(分别)锁。因此,要删除分区,您肯定希望拥有对该分区的 X 访问权限,但您首先需要拥有对该表的 IX、对该数据库的 IX 和对该数据中心的 IX。如果有人想要对数据库进行快照,他们需要拥有对该数据库的 S 访问权限和对该数据中心的 IS 访问权限。数据库级别的 S 和 IX 之间的冲突很快就会被检测到,并且有人必须等待。在 InnoDB 中,我们只有这个层次结构的两个级别:表级别和行级别。(实际上,如果您发现这种“嵌套作用域”类比很有帮助,那么您可能会喜欢这样一种观点,其中“行之前的间隙”也是一个作用域,S,GAP 和 X,GAP 锁是“间隙级别的 S 锁”,而 INSERT_INTENTION 锁就像“间隙级别的 IX 锁”。请注意名称中的“INTENTION”,这不是巧合!)

Short note on AUTO_INC locks

它们与其他任何东西都不同。有很多特殊情况的代码和逻辑可以使插入大量行尽可能高效。您可能会认为我在本系列中写的任何内容都不一定适用于它们,除非我这么说。首先,它们通常根本不被占用——在增量持续时间内获取保护序列计数器的短暂闩锁【latch】,并尽快释放。如果被占用,它们可能会在语句结束时被释放,而不是被保留到事务结束。有关更多详细信息,请参阅我们的参考手册中的 InnoDB 中的 AUTO_INCREMENT 处理。

Record locks

如前所述,InnoDB 中的大多数锁定活动都发生在记录级别,但我发现 InnoDB 表锁更容易解释,因为其中可能的锁定模式较少(只有 5 种:X、S、IS、IX、AUTO_INC),并且冲突关系是对称的,这使得理解必要的概念更容易。

InnoDB 是一个庞大的软件,因此必须讨论一些关于正在发生的事情的抽象,而不是被细节淹没。因此,请原谅我的过度简化:我们将想象索引中的一行只是轴上的一个点。也就是说,每个索引都被建模为一个单独的轴,如果你按升序列出索引中的行,则会得到一些沿此轴从左到右的离散点集:

可以概念化为:

 --(5)---(10)-----(42)---> id

我们的心理形象应该由点和它们之间的间隙组成:

最右边的间隙比较特殊,因为它不在任何实际行之前。你可以想象一个“无穷大”的伪记录,它比任何其他记录都大,因此最右边的间隙是“伪记录之前”。

实际上,在非过于简化的 InnoDB 中,这个问题发生在每个数据页中:有时我们需要讨论这个特定页面上最后一条记录后的间隙。是的,从概念上讲,这与下一页上第一条记录之前的间隙相同。但是,我们经常处于无法访问下一页的情况,但需要以某种方式讨论/识别/操作此间隙。因此,InnoDB 中的每个页面都有一个最高伪记录。有一种普遍的误解,认为“最高伪记录”标志着整个索引的结束。这是不对的,索引的每个叶节点中都有一个伪记录。

即使不太了解像 InnoDB 等这样的数据库如何运作,我们也可以猜测,有时操作只涉及记录,有时涉及记录之前的间隙,而有时我们需要访问记录和间隙。一种建模方法是将记录和间隙视为两种可以独立锁定的不同类型的资源。当前的 InnoDB 实现采用了一种不同的方法:每个点只有一个资源,但您可以为其请求多种访问权限,该访问权限指定您是否需要行、间隙还是两者都需要。这样做的一个好处是,它针对最常见的需要两者的情况进行了优化。

InnoDB 中目前定义了许多不同的访问权限,它们在 performance_schema.data_locks.lock_mode 列中使用以下字面值表示:

  • S,REC_NOT_GAP → 对记录本身的共享访问
  • X,REC_NOT_GAP → 对记录本身的独占访问
  • S,GAP → 阻止任何人在行前的间隙中插入任何内容的权限
  • X,GAP → 同上。是的,“S” 和 “X” 是“shared”和“exclusive”的缩写,但鉴于此访问权限的语义是“防止插入发生”,多个线程都可以同意在没有任何冲突的情况下防止相同的事情发生,因此目前 InnoDB 以相同的方式处理 S,GAP 和 X,GAP (或简称  *,GAP  锁):与  *,INSERT_INTENTION 冲突
  • S → 就像是 S,REC_NOT_GAP 和 S,GAP 的组合。所以它是对行的共享访问,并阻止该行之前的间隙插入。
  • X → 就像是 X,REC_NOT_GAP 和 X,GAP 的组合。因此,它是对该行的独占访问,并阻止该行之前的间隙插入。
  • X,GAP,INSERT_INTENTION → 有权将新行插入到该行之前的间隙中。尽管名称中带有“X”,但它实际上与同时尝试插入的其他线程相互兼容。
  • X,INSERT_INTENTION → 在概念上与上述相同,但只发生在“最大伪记录”中,它是“大于页面上任何其他记录”的伪记录,因此“它之前”的间隙实际上是“最后一条记录之后的间隙”。

以上列表是实现细节,将来可能会发生变化。可能会保留的想法是,存在许多“锁定模式【lock modes】”和一组规则来决定模式 A 中的访问请求是否必须等待模式 B 中访问资源的事务完成。这可以通过类似以下矩阵给出:

↓requested \ held→S,REC_NOT_GAPX,REC_NOT_GAP*,GAPSX*,INSERT_INTENTION
S,REC_NOT_GAP
X,REC_NOT_GAP
*,GAP
S
X
*,INSERT_INTENTION

需要注意以下几点:

  • 没有人关心已授予的  INSERT_INTENTION。这是因为此访问权限在授予后立即被“使用【consumed】”:事务立即将新记录插入数据库,这会导致(旧)行之前的间隙分裂成两个间隙,因此在某种意义上,旧访问权限不再需要/有效,因此被忽略。
  • 无论如何,*,GAP 锁都会立即被授予。这在稍后我将描述的“锁分裂”技术中被大量使用
  • 特别是, INSERT_INTENTION  必须等待  *,GAP ,但反过来则不必如此——冲突关系不对称【symmetrical】!
  • INSERT_INTENTION 必须等待 S, 必须等待 X,REC_NOT_GAP,但是INSERT_INTENTION 不必等待  X,REC_NOT_GAP——冲突关系不是传递的【transitive】!

INSERT_INTENTION 必须等待 S,S 必须等待 X,REC_NOT_GAP,但 INSERT_INTENTION 不必等待 X,REC_NOT_GAP

再说一遍:这些是实现细节,可能会在未来版本中发生变化。重要的是要认识到,数据库引擎可以具有比简单的 Read 和 Write 更复杂的访问权限集,并且它们之间的冲突关系可以是任意的(甚至不是对称的或传递的)。

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

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

相关文章

【Mac】关于Mac的github配置和本地项目上传

目录 前言什么是github?有什么用?github个人账户创建Mac的git环境配置生成密钥将密钥添加到github 创建github仓库将本地文件上传至github仓库一些常用的git命令总结 前言 本文主要介绍了Mac的git环境配置&#xff0c;github仓库的创建&#xff0c;本地文件上传到github仓库以…

分享268款漂亮的3D模型和视觉效果的制作和展示源码

分享268款漂亮的3D模型和视觉效果的制作和展示源码&#xff0c;总有一款是你需要的&#xff0c;源码演示下载地址如下&#xff1a;https://www.erdangjiade.com/js/178-0-0-0 Html跨年烟花代码&#xff0c;JS实现烟花表白代码 最新程序员表白我爱你玫瑰花代码 纯CSS3实现3D Tw…

【赠书第26期】AI绘画教程:Midjourney使用方法与技巧从入门到精通

文章目录 前言 1 Midjourney入门指南 1.1 注册与登录 1.2 界面熟悉 1.3 基础操作 2 Midjourney进阶技巧 2.1 描述词优化 2.2 参数调整 2.3 迭代生成 3 Midjourney高级应用 3.1 创意启发 3.2 团队协作 3.3 商业应用 4 总结与展望 5 推荐图书 6 粉丝福利 前言 在…

Oracle导出clob字段到csv

使用UTL_FILE ref: How to Export The Table with a CLOB Column Into a CSV File using UTL_FILE ?(Doc ID 1967617.1) --preapre data CREATE TABLE TESTCLOB(ID NUMBER, MYCLOB1 CLOB, MYCLOB2 CLOB ); INSERT INTO TESTCLOB(ID,MYCLOB1,MYCLOB2) VALUES(1,Sample row 11…

标准化产品需求文档逻辑思路

​PRD被公认为产品经理的标准文档&#xff0c;但你写PRD文档时是否做过这些事&#xff1a; 1.下载模版&#xff0c;填入内容&#xff1b; 2.不了解的章节内容&#xff0c;略过或删掉&#xff1b; 3.找己经做好的PRD&#xff0c;做内容替换。 以前我所在的公司&#xff0c;PRD管…

用Idea 解决Git冲突

https://intellijidea.com.cn/help/idea/resolving-conflicts.html https://www.jetbrains.com/help/idea/resolve-conflicts.html idea 官方文档 当您在团队中工作时&#xff0c;您可能会遇到这样的情况:有人对您当前正在处理的文件进行更改。如果这些更改没有重叠(也就是说…

Linux系统使用Docker安装Drupal结合内网穿透实现远程访问管理后台

目录 前言 1. Docker安装Drupal 2. 本地局域网访问 3 . Linux 安装cpolar 4. 配置Drupal公网访问地址 5. 公网远程访问Drupal 6. 固定Drupal 公网地址 前言 作者简介&#xff1a; 懒大王敲代码&#xff0c;计算机专业应届生 今天给大家聊聊Linux系统使用Docker安装Drupal…

接口测试工具:Postman的下载安装及使用

1 Postman 介绍 1.1 Postman 是什么 Postman 是一款功能超级强大的用于发送 HTTP 请求的 测试工具 做 WEB 页面开发和测试的人员常用工具 创建和发送任何的 HTTP 请求(Get/Post/Put/Delete...) 1.2 Postman 相关资源 1.2.1 官方网站&#xff1a;https://www.postman.com/ …

CCIG 2024:合合信息文档解析技术突破与应用前景

目录 背景当前大模型训练和应用面临的问题训练Token耗尽训练语料质量要求高LLM文档问答应用中文档解析不精准 合合信息的文档解析技术1. 具备多文档元素识别能力2. 具备版面分析能力3. 高性能的文档解析4. 高精准、高效率的文档解析文档多板式部分示例 文档解析典型技术难点元素…

基于Java的KTV点歌系统

开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术&#xff0c;JAVA&#xff0c;B/S架构 工具&#xff1a;浏览器&#xff08;360浏览器、谷歌浏览器、QQ浏览器等&#xff09;&#xff0c;数据库管理工具&#xff08;MySQL&#xff09; 系统展示 …

GPT-4o:人工智能技术的新巅峰

人不走空 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌赋&#xff1a;斯是陋室&#xff0c;惟吾德馨 目录 &#x1f308;个人主页&#xff1a;人不走空 &#x1f496;系列专栏&#xff1a;算法专题 ⏰诗词歌…

DBeaver连接Oracle报错:ORA-12514

Listener refused the connection with the following error:ORA-12514, TNS:listener does not currently know of service requested inconnect descriptor ———————————————— 1.报错信息2.配置正确结语 ———————————————— 如果是第一次连接Or…

IP地址开启HTTPS方法

可以使用IP地址申请SSL证书&#xff0c;申请之前必须是公网IP地址&#xff0c;不支持内网IP地址申请。 申请过程需要确定IP地址外网可以访问&#xff0c;这里特别注意只是申请过程中可以访问。访问验证过程必须采取80端口、443端口两者选择1个&#xff0c;不可以用其它端口进行…

「手把手prompt1」相关介绍

「手把手prompt1」相关介绍 在人工智能领域迅速发展的当下&#xff0c;“prompt” 这个术语正逐渐成为焦点。本文将带您深入了解prompt的本质&#xff0c;以及它如何影响我们与AI系统的互动。您将学习到&#xff0c;通过精确的指令设计&#xff0c;可以引导AI系统产出精确和有…

使用Minikube+docker+harbor+k8s自动化部署 @by_TWJ

目录 1. 开始1.1. 环境1.2. 测试的git仓库1.3. 离线文件1.4. 安装docker1.5. 安装docker-compose&#xff08;非必要&#xff09;1.6. 安装Jenkins1.7. 安装harbor1.8. 允许docker通过http访问私有仓库1.9. 修改/etc/hosts&#xff0c;追加自定义域名1.10. 安装Minikube 2. min…

【JavaScript】ECMAS6(ES6)新特性概览(一):变量声明let与const、箭头函数、模板字面量全面解析

&#x1f525; 个人主页&#xff1a;空白诗 &#x1f525; 热门专栏&#xff1a;【JavaScript】 文章目录 &#x1f33f; 引言一、 let 和 const - 变量声明的新方式 &#x1f31f;&#x1f4cc; var的问题回顾&#x1f4cc; let的革新&#x1f4cc; const的不变之美 二、 Arro…

CasaOS玩客云安装全平台高速下载器Gopeed并实现远程访问

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Spring-Cloud-CircuitBreaker-Resilience4j (3.1.1)

介绍 Resilience4j 是一个专为函数式编程而设计的轻量级容错库。Resilience4j 提供高阶函数&#xff08;装饰器&#xff09;&#xff0c;以增强任何功能接口、lambda 表达式或方法引用&#xff0c;包括断路器、速率限制器、重试或隔板。您可以在任何函数接口、lambda 表达式或…

每日复盘-20240530

今日重点关注&#xff1a; 20240530 六日涨幅最大: ------1--------300637--------- 扬帆新材 五日涨幅最大: ------1--------300637--------- 扬帆新材 四日涨幅最大: ------1--------300637--------- 扬帆新材 三日涨幅最大: ------1--------301129--------- 瑞纳智能 二日涨…

Stable Diffusion AI绘画:从创意词汇到艺术图画的魔法之旅

文章目录 一、Stable Diffusion的工作原理二、从提示词到模型出图的过程三、Stable Diffusion在艺术创作中的应用《Stable Diffusion AI绘画从提示词到模型出图》内容简介作者简介楚天 目录前言/序言本书特色特别提示 获取方式 在科技的飞速发展中&#xff0c;Stable Diffusion…