在数据库组件中,一些组件是专用的,如词法解析只用于SQL引擎;而另外一些组件是公共的,用于整个数据库系统。openGauss的公共组件包括系统表、数据库初始化、多线程架构、线程池、内存管理、多维监控和模拟信号机制等。每个组件实现了一个独立的功能。本章对公共组件的源代码实现进行介绍。
3.1 系统表
系统表又称为数据字典或者元数据,存储管理数据库对象的定义信息,如表、索引、触发器等。用户可通过系统表查询用户定义的具体对象信息,如表的每个字段类型。因为openGauss支持一个实例管理多个数据库,所以系统表分为实例级别的系统表和数据库级别的系统表。实例级别的系统表在一个实例管理的多个数据库之间共享,整个实例只有一份,这些系统表为pg_authid、pg_auth_members、pg_database、pg_db_role_setting 、pg_tablespace、pg_shdepend、pg_shdescription、pg_shseclabel。数据库级别的系统表比如pg_class,pg_depend,pg_index,pg_attribute等,每个数据库各有一份。
3.1.1 系统表的定义
openGauss系统表定义全部在src/include/catalog目录下,每个头文件就是一个系统表的定义。如pg_database.h就是对pg_database的定义。在pg_database.h中,主要包括pg_database的表OID(object identifier,对象标识符)、类型OID、结构体定义、字段个数和每个字段ID(identifier,标识符)枚举值、数据库初始化默认值。下面是代码及其具体解释:
#define DatabaseRelationId 1262
/* pg_database本身也是一个结构类型,DatabaseRelation_Rowtype_Id表示pg_database在系统表pg_type中的OID为1248 */
#define DatabaseRelation_Rowtype_Id 1248
/* pg_database本身也是一个结构类型,DatabaseRelation_Rowtype_Id表示pg_database在系统表pg_type中的OID为1248 */
/* BKI_SHARED_RELATION表示pg_database是实例级别的系统表 */
CATALOG(pg_database,1262) BKI_SHARED_RELATION BKI_ROWTYPE_OID(1248) BKI_SCHEMA_MACRO
{
NameData datname; /* 数据库名称 */
Oid datdba; /* 数据库拥有者 */
int4 encoding; /* 字符集编码 */
NameData datcollate; /* LC_COLLATE 设置值 */
NameData datctype; /* LC_CTYPE 设置值 */
bool datistemplate; /* 是否允许作为模板数据库*/
bool datallowconn; /* 是否允许链接 */
int4 datconnlimit; /* 最大连接数*/
Oid datlastsysoid; /* 系统OID最大值*/
ShortTransactionId datfrozenxid; /* 冻结事务ID,所有小于这个值的事务ID已经冷冻。为了兼容原来的版本,使用32位事务ID*/
Oid dattablespace; /* 数据库的缺省表空间 */
NameData datcompatibility;/* 数据库兼容模式,比如除0是报错还是当做正常处理*/
#ifdef CATALOG_VARLEN /* 下面字段是变长字段 */
aclitem datacl[1]; /* 访问权限*/
#endif
TransactionId datfrozenxid64; /* 冷冻事务ID,64-bit(比特)事务ID */
} FormData_pg_database;
CATALOG的宏定义代码为:
#define CATALOG(name,oid) typedef struct CppConcat(FormData_,name)
因此CATALOG(pg_database,1262)就是对结构体FormData_pg_database的定义。之所以采用CATALOG,是因为这个格式是和BKI(backend interface,后端接口)脚本约定的格式,BKI脚本根据这个格式生成数据库的建表脚本。
接下来是数据库对象字段总数和每个字段ID的值的定义代码,定义这些值的目的主要代码访问数据库对象时清晰、方便维护、避免魔鬼数字(魔鬼数字指在代码中没有具体含义的数字、字符串。魔鬼数字会影响代码可读性,使读者无法理解看到的数字对应的含义,从而难以理解程序的意图)。
#define Anum_pg_database_datname 1
#define Anum_pg_database_datdba 2
#define Anum_pg_database_encoding 3
#define Anum_pg_database_datcollate 4
#define Anum_pg_database_datctype 5
#define Anum_pg_database_datistemplate 6
#define Anum_pg_database_datallowconn 7
#define Anum_pg_database_datconnlimit 8
#define Anum_pg_database_datlastsysoid 9
#define Anum_pg_database_datfrozenxid 10
#define Anum_pg_database_dattablespace 11
#define Anum_pg_database_compatibility 12
#define Anum_pg_database_datacl 13
#define Anum_pg_database_datfrozenxid64 14
最后是创建数据库时的默认数值。代码中的值表示默认创建template1数据库,DATA的字段值和数据库结构体的值一一对应。对应代码如下:
SHDESCR("default template for new databases");
#define TemplateDbOid 1
#define DEFAULT_DATABASE "postgres"
系统表头文件的内容和格式基本类似。
3.1.2 系统表的访问
系统表定义后,接下来介绍数据库在运行过程中对系统表的访问。openGauss对系统表的访问主要是通过syscache机制。syscache机制是一个通用的机制,主要对系统表的数据进行缓存,提升系统表数据的访问速度,详细细节参照具体章节描述。这里主要描述与pg_database相关的部分。pg_database在枚举类型enum SysCacheIdentifier中定义的枚举值有一个:DATABASEOID,表示根据数据库OID访问pg_database系统表。同时需要把pg_database系统表访问模式添加到“struct cachedesc cacheinfo”中。与pg_database相关的代码如下:
DatabaseOidIndexId,
1,
{ObjectIdAttributeNumber, 0, 0, 0},
4},
这几个值与cachedesc结构体的字段对应,表示pg_database表的OID值、索引的OID值、搜索时有1个key字段、搜索key字段ID为ObjectIdAttributeNumber、初始化为4个hash桶。相关的代码如下:
Oid reloid; /* 缓存的表的OID */
Oid indoid; /* 缓存数据的索引OID */
int nkeys; /* 缓存搜索的key的个数 */
int key[4]; /* key属性的编号*/
int nbuckets; /* 缓存hash桶的个数*/
};
系统表的定义和访问主要逻辑如上问所述。与pg_database相关的SQL命令是ALTER DATABASE、CREATE DATABASE、DROP DATABASE,这些命令执行的结果是把数据库相关的信息存储到pg_database系统表中。
其他系统表的逻辑与pg_database相似,不再重复。