本章阐述PostgreSQL核心系统与表访问方法间的接口,其管理表的存储。除这里指出的内容,核心系统对于这些访问方法知之甚少,因此可以通过编写附加代码来开发全新的访问方法类型。
每个表访问方法都有pg_am
系统目录中的一行来描述。pg_am
条目为表访问方法指定一个名字和句柄函数。这些条目可以用SQL命令CREATE ACCESS METHOD和DROP ACCESS METHOD来创建和删除。
表访问方法句柄函数必须声明成接受单个internal
类型的参数,并返回伪类型table_am_handler
。该参数是伪值,仅用于防止从SQL命令直接调用句柄函数。
函数的结果必须是指向类型TableAmRoutine
的结构的指针,其包含了核心代码所需要知道的所有内容,以利用表访问方法。返回值需具有服务器生命周期,通常是通过将其定义为一个全局范围的static const
变量来实现。TableAmRoutine
结构,也称为访问方法的API结构,定义使用回调的访问方法的行为。这些回调是普通C函数指针,在SQL级别并不可见或者可调用。所有回调及其行为在TableAmRoutine
结构中定义(结构内部有定义回调需求的注释)。大多数回调有包装函数,从用户(而不是实现者)视点记录表访问方法。详细信息请参考 src/include/access/tableam.h
文件。
为了实现访问方法,实现者通常要实现特定AM类型的元组表槽(见 src/include/executor/tuptable.h
),允许访问方法之外的代码保存对AM元组的引用,并且能访问元组的列。
目前AM存储数据的实际方式完全没有限制。例如,可以使用postgres的共享缓冲区的缓存,但这并非必需的。如果使用它,使用第 70.6 节中所述的PostgreSQL的标准页面布局可能很有意义。
当前表访问方法API的一个相当大的限制是,如果AM要支持修改和/或索引,每个元组都需要有由块号和项目号组成的元组标识符(TID)(见第 70.6 节)。TIDs的子部分不一定具有与堆
相同的含义,但如果需要位图扫描支持(可选),则块号需要提供局部性。
为安全起见,AM可使用postgres的WAL或自定义实现。如果选用了WAL,则可使用通用WAL记录或实现新型的WAL记录。通用WAL记录较简单,但意味着WAL量更高。目前实现新型WAL记录需要修改核心代码(特别是src/include/access/rmgrlist.h
)。
要以允许在单个事务中访问不同表访问方法的方式实现事务支持,可能需要与src/backend/access/transam/xlog.c
中的机制紧密集成。
新的表访问方法
的开发人员可参考src/backend/access/heap/heapam_handler.c
中已有的堆
实现代码,以了解其实现的细节。