postgres的initdb解析——从一次插件升级失败说起

我们公司基于postgres开发了一款数据库产品,不用说我们对OSS的源码做了改动,并且也集成和自己编写了一些插件。因此,当postgresql和相关插件升级时,我们也需要将升级反应到自己的产品中去,这是背景。

这次的问题是在我们升级postgresql的插件orafce(3.2.0-->3.6.0)时发生的。按照往常惯例我们将该插件升级后,组织源码进行编译,OK编译通过。

然而,在我们进行测试时,程序在initdb时就报错停止了。报错如下:

[[email protected] data]$ initdb -D `pwd`
The files belonging to this database system will be owned by user "postgres".
This user must also own the server process.

The database cluster will be initialized with locale "en_US.UTF-8".
The default database encoding has accordingly been set to "UTF8".
The default text search configuration will be set to "english". (15541)

Data page checksums are disabled. (18153)

fixing permissions on existing directory /data ... ok (15516)
creating subdirectories ... ok (15516)
selecting default max_connections ... 100
selecting default shared_buffers ... 128MB
selecting dynamic shared memory implementation ... posix
creating configuration files ... ok (15516)
creating template1 database in /data/base/1 ... ok (15516)
initializing pg_authid ... ok (15516)
initializing dependencies ... ok (15516)
creating information schema ... FATAL: relation "information_schema.columns" does not exist (10414)
......
(以下省略)

众人费解。只是升级了插件,怎么会导致无法创建initdb呢?

我注意到报错中的这行:

creating information schema ... FATAL: relation "information_schema.columns" does not exist (10414)

似乎挺熟悉?我看看了orafce最新的升级文件。发现在文件中有以下SQL文:

-- Oracle system views
create view oracle.user_tab_columns as
    select table_name,
           column_name,
           data_type,
           coalesce(character_maximum_length, numeric_precision) AS data_length,
           numeric_precision AS data_precision,
           numeric_scale AS data_scale,
           is_nullable AS nullable,
           ordinal_position AS column_id,
           is_updatable AS data_upgraded,
           table_schema
    from information_schema.columns;

似乎对上了,真的是升级惹的祸?不应该啊,社区应该没这么蠢啊,再说只是个插件,怎么会影响postgres呢?这个时候还没导入插件呢,怎么会存在这个错误?

困惑。

因为我们产品中的postgresql的代码也有我们自己添加的代码,为了确定错误来源,我先取了一份postgresql的source,在contrib目录下放入最新的orafce代码。然后make world。

在运行initdb命令:

(以上省略)
copying template1 to postgres ... ok (15516)
syncing data to disk ... ok (15516)

WARNING: enabling "trust" authentication for local connections
You can change this by editing pg_hba.conf or using the option -A, or
--auth-local and --auth-host, the next time you run initdb.

Success. You can now start the database server using:

    pg_ctl -D /data -l logfile start

成功了!说明不是OSS的问题。

很好,那么就是我们的修正代码的问题了。然而initdb这一块代码不是我们team维护的,我不知道我们的产品修改了什么。好的,老老实实看看差分代码吧。

结果差分代码一看,initdb.c文件我们就修改了两行代码,看了看,也只是改善性代码,和本次的问题毫无关系。费解。。。。

好吧,既然是initdb出了问题,我看看initdb的代码,理理思路吧。跑过去看看抛出出错信息的代码。再加上自己的整理。大概搞清楚了原因。

具体是什么原因先卖个关子。我们先看看postgresql在initdb时会执行哪些操作(缩进代表调用关系):

main
    确保stdout和stderr的缓冲行为与交互式使用中的行为相匹配
    设置特定于应用程序的区域设置和服务目录
    process command-line options
    sync_only模式
    密码与服务器认证相关
    setup_pgdata()设置pgdata环境
    setup_bin_paths()获取postgres命令的路径,判断是否与initdb版本匹配
    set_info_version()提取信息模式所需的版本号
    setup_data_file_paths() check初始化脚本和配置文件模板
    setup_locale_encoding()设置编码方式
    setup_text_search()根据encoding设置text search方式
    do_sync模式
    initialize_data_directory
        create_data_directory()创建数据库目录pgdata
        create_xlog_or_symlink()创建pgdata下的pg_xlog目录
        创建其他子目录
        创建并配置postgresql.conf文件
        bootstrap_template1()调用postgres在Bootstrap模式下创建模板数据库template1
        (以下的配置均针对模板数据库template1)
        setup_auth()设置template1的密码表
        setup_depend()建立系统表pg_depend,该表描述了数据库对象之间的依赖关系
        setup_sysviews()运行脚本system_views.sql创建系统视图★
        setup_description()创建系统表pg_description和pg_shdescription
        setup_collation()创建系统表pg_collation,该表描述了可用的排序规则,其本质是从一个SQL名字到操作系统locale分类的映射
        setup_conversion()运行脚本conversion_create.sql创建系统表pg_conversion,该表描述编码转换过程
        setup_dictionary()运行脚本snowball_create.sql创建一些额外的目录
        setup_privileges()为postgres内置的一些object设置默认权限
        setup_schema()运行脚本information_schema.sql创建模式information_schema★
        load_plpgsql()加载plpgsql服务端编程语言
        vacuum_db()清理template1
        make_template0()根据做好的template1,拷贝复制一份作为template0
        make_postgres()根据做好的template1,拷贝复制一份作为postgres
    告诉用户initdb执行结束

以上就是initdb的执行过程。很清晰也很简单。其中最重要的是initialize_data_directory()函数。正是该函数一步步地建立起了数据库的基本元素。因此,出问题的地方就在这个函数"内部"。

聪明的朋友可能看出来了,我在上面打了两处"★"。是的,没有错,正是这两块代码的问题,哦不,确切的说是sql的问题。

下面来说。

我们可爱的开发人员在system_views.sql中加入了以下两行(询问发现是客户希望使用orafce功能,但又不想手动创建,想"透明"地使用):

CREATE EXTENSION orafce;
SET search_path TO DEFAULT;

我们知道orafce的初始化引用了 information_schema.columns这个视图,而这个视图在information_schema.sql中被创建。

而由上面的initdb执行过程可以看到:system_views.sql的执行顺序在information_schema.sql之前,也是就说:
我们在初始化 orafce的时候,information_schema.columns还不存在,因此,会在执行system_views.sql时,报以上错误。

知道了原因就很好改了,只要保证加入的那两行sql代码在创建information_schema之后即可~

以上

原文地址:https://www.cnblogs.com/flying-tiger/p/8385208.html

时间: 2024-10-06 15:56:11

postgres的initdb解析——从一次插件升级失败说起的相关文章

Sublime Text 无法使用Package Control或插件安装失败的解决方法

Sublime Text用了一年多了,公司搬家近期突然发现Package Control无法安装新插件了.尽管不影响原有功能的使用.还是要解决它.因为本人用Windows系统,仅仅讨论Windosw下的解决方法. Mac与Linux下的用户能够參照解决. 本文主要介绍Sublime Text怎样开启debug模式.分析使用过程中一些常见错误情形的解决方法. 情形一:Package Control:There are no packages available for installation.情

Sublime Text 无法使用Package Control或插件安装失败的解决方法(转)

Sublime Text用了一年多了,公司搬家最近突然发现Package Control无法安装新插件了,虽然不影响原有功能的使用,还是要解决它.由于本人用Windows系统,只讨论Windosw下的解决方法.Mac与Linux下的用户可以参照解决. 本文主要介绍Sublime Text如何开启debug模式,分析使用过程中一些常见错误情形的解决方法.情形一:Package Control:There are no packages available for installation.情形二:

解决xcode插件升级失效的命令

解决xcode插件升级失效的命令 find ~/Library/Application\ Support/Developer/Shared/Xcode/Plug-ins -name Info.plist -maxdepth 3 | xargs -I{} defaults write {} DVTPlugInCompatibilityUUIDs -array-add `defaultsread /Applications/Xcode.app/Contents/Info.plist DVTPlugI

java.lang.NoSuchMethodError,jenkins插件升级导致问题报错

Started by user test java.lang.NoSuchMethodError: org.eclipse.jgit.lib.Repository.getRef(Ljava/lang/String;)Lorg/eclipse/jgit/lib/Ref; at jenkins.plugins.git.GitSCMFileSystem$1.invoke(GitSCMFileSystem.java:117) at jenkins.plugins.git.GitSCMFileSystem

glpi资产管理系统及fusion插件升级9.3->9.4

glpi:9.3.1-->9.4.5fusioninventory: 9.3-->9.4 1.备份 备份数据库 备份文件数据 备份配置数据 2.获取新的安装包glpi安装包获取地址:https://github.com/glpi-project/glpi/releasesfusion安装包获取地址: https://plugins.glpi-project.org/#/plugin/fusioninventory 3.解压更新浏览器输入IP/glpi进行访问:按照要求进行升级: yum ins

微信小程序 —— 微信小程序解析html富文本插件wxParse

下载并把wxParse放到小程序的目录中 github下载地址:https://github.com/icindy/wxParse 一.基本使用方法 1. Copy文件夹wxParse,把wxParse放在与page同一级目录 - wxParse/ -wxParse.js(必须存在) -html2json.js(必须存在) -htmlparser.js(必须存在) -showdown.js(必须存在) -wxDiscode.js(必须存在) -wxParse.wxml(必须存在) -wxPars

eclipse插件安装失败的列表如何清除-一个困扰很久的问题

平时在安装eclipse插件的时候由于网络不稳定或者下载下来的包不兼容等原因安装失败的情况很多, 但是当插件安装一次以后,就会在安装的url中留下历史记录,并且每次切换到安装插件的界面中时,后台都要检查一遍,并且弹出相同的错误窗口,导致很多其他的插件也无法安装. 这里教大家怎么清除下图中安装遗留下来的历史记录. 在windows ->Perferences -> Install/Update -> Available Software Sites 右侧选中要清除的记录,单击Remove即

四级地址插件升级改造(京东商城地址选择插件)city-picker

最近公司做的项目要和京东的数据做对接,所以要做个类似京东商品的详情页.页面的数据,是可以从京东接口获取到的,但是地址插件选择的效果需要自己实现.前端的同事在之前的项目中,已经选择了一款地址插件(city-picker.js),但是这款插件最多只支持三级地址,而且最主要的是这插件的地址数据来源,是写死在一个json文件中的,意思就是说,在使用这个插件的时候页面要一次性的把所有的地址数据都加载出来,这在pc端一般倒还可以承受,但是到了,移动端,随便一个手机就会卡死,浏览器直接崩溃. 经过在网上的各种

vscode插件安装失败的解决方案

在vscode中点击对应插件的install按钮安装,安装失败,软件提示手动安装(manually install). 手动下载vsix安装包,然后点击install from VSIX...,选择vsix安装包进行安装,显示Error: EACCES: permission denied, mkdir ... 这种情况一般来说是因为权限问题,使得安装过程无法对一些文件进行操作. 通过查阅,在github上的vscode项目找到了对应的解决方案(参考:https://github.com/Mic