# 57.5.外国数据包装器中的行锁定

如果FDW的底层存储机制具有锁定单个行以防止这些行并发更新的概念,那么FDW通常值得执行行级锁定,并且与普通PostgreSQL表中使用的语义尽可能接近。这涉及到多方面的考虑。

要作出的一个关键决定是是否执行早期锁定延迟锁定. 在早期锁定中,当第一次从底层存储检索行时,行被锁定,而在后期锁定中,只有当知道需要锁定时,行才会被锁定。(差异产生的原因是,某些行可能会被本地检查的限制或连接条件丢弃。)早期锁定更简单,避免了额外的往返到远程存储,但它可能会导致不需要锁定的行的锁定,从而减少并发性,甚至意外死锁。此外,只有在以后可以唯一地重新标识要锁定的行时,才可能延迟锁定。最好行标识符应该标识行的特定版本,就像PostgreSQL TIDs所做的那样。

默认情况下,PostgreSQL在与FDWs接口时忽略锁定注意事项,但是FDW可以在不需要核心代码的任何显式支持的情况下执行早期锁定。中描述的API函数第57.2.6节,在PostgreSQL 9.5中添加了该功能,允许FDW在需要时使用延迟锁定。

另一个考虑是已提交的读取隔离模式,PostgreSQL可能需要根据某些目标元组的更新版本重新检查限制和连接条件。重新检查连接条件需要重新获取以前加入到目标元组的非目标行的副本。在使用标准PostgreSQL表时,可以通过将非目标表的TID包含在通过联接投影的列列表中,然后在需要时重新获取非目标行。这种方法保持连接数据集的紧凑性,但它需要廉价的重新获取功能,以及一个能够唯一标识要重新获取的行版本的TID。因此,默认情况下,与外部表一起使用的方法是在通过联接投影的列列表中包含从外部表中获取的整行的副本。这对FDW没有特殊要求,但会导致合并和哈希连接的性能降低。能够满足重新获取需求的FDW可以选择第一种方式来执行。

为了一个使现代化删去在国外桌子上,建议外国扫描目标表上的操作对它获取的行执行早期锁定,可能是通过选择更新.FDW可以检测表是否为使现代化/删去通过比较relid和根->解析->结果关联,或在执行时使用ExecRelationStarGetRelation()。另一种可能性是在ExecForeignUpdateExecForeignDelete回调,但没有为此提供特殊支持。

对于指定由选择更新/共享指挥部外国扫描操作可以通过使用等效于选择更新/共享。要执行延迟锁定,请提供中定义的回调函数第57.2.6节在里面GetForeignRowMarkType,选择行标记选项ROW_MARK_独家, 排_MARK _NOKEYEXCLUSIVE, 排_标记_共享行标记键共享取决于请求的锁定强度。(无论您选择这四个选项中的哪一个,核心代码的作用都是相同的。)在其他地方,您可以使用得到你的计划在计划时间,或者ExecFindRowMark在执行时;您不仅必须检查是否返回了非空的rowmark结构,还必须检查其力量菲尔德不是.

最后,对于在使现代化, 删去选择更新/共享命令,但未指定为行锁定,则可以通过GetForeignRowMarkType选择选项行标记参考当它看到锁的力量.这会导致RefetchForeignRow被称为标记类型; 然后,它应该在不获取任何新锁的情况下重新获取行。(如果你有GetForeignRowMarkType函数,但不希望重新获取未锁定的行,请选择选项行标记副本对于.)

看见src/include/nodes/lockoptions。H的评论行标记类型普朗罗马克在里面src/include/nodes/plannodes。H,以及ExecRowMark在里面src/include/nodes/execnodes。H了解更多信息。