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

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

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

[postgres@localhost 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之后即可~

以上

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

  1. taskctl命令行类(sh、exe、python新增scp)插件升级扩展

    转载自: http://www.taskctl.com/forum/detail_129.html 上次写了一个帖子 TASKCTL中不使用代理,通过ssh免密连接执行远程脚本配置(SSH插件扩展)h ...

  2. 【Devops】【Jenkins】Jenkins插件安装失败处理方法

    本篇解释:Jenkins插件安装失败处理方法 不论是刚启动成功后进行的推荐插件安装,还是后期使用Jenkins过程中进行插件的安装.出现插件安装失败的问题,可以通过本篇解决! [注意,插件下载安装失败 ...

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

    Sublime Text用了一年多了,公司搬家近期突然发现Package Control无法安装新插件了.尽管不影响原有功能的使用.还是要解决它.因为本人用Windows系统,仅仅讨论Windosw下 ...

  4. egret inspect插件安装失败处理方法

    egret inspect插件安装失败处理方法谷歌浏览器版本太高不兼容了 换个69就行了 然后点击加载已解压的扩展程序选择EgretInspector-v2.5.5这个文件夹 就安装成功了 重启下浏览 ...

  5. Jenkins中插件下载失败的解决办法

    插件下载失败原因:通过国外服务器下载镜像,有较高的失败率,某些插件下载失败或者中断会引起其他有依赖关系的插件也下载失败 解决方案:1. 使用VPN.2. Jenkins镜像地址改为国内镜像地址:系统管 ...

  6. 解决 VS Code 中 golang.org 被墙导致的 Go 插件安装失败问题

    微软官方开发的 Go for Visual Studio Code 插件为 Go 语言 提供了丰富的支持.在 VS Code 中首次打开 Go 工作区后,VS Code 会自动检测当前开发环境为 Go ...

  7. Jenkins插件安装失败

    插件安装失败 通常要下载国外的软件插件之类的时候,链接到国外会太慢或者被墙,这就需要我们去换镜像源 修改配置文件 我们在jenkins里更改升级站点的url后 若安装插件时还是一直卡在"安装 ...

  8. json解析—Gson以及GsonFormat插件的运用

    最近开始慢慢做毕业设计了,遇到一个功能是获取天气预报的,我选择的是和风天气的api,返回的是JSON数据,所以遇到了解析JSON的问题 首先简单说下JSON,JSON(JavaScript Objec ...

  9. 小程序解析html标签wxPrase插件

    微信小程序的标签和原来我们习惯用的标签是不一样的,例如视图容器标签小程序是view,然而html就很多比如常用的div就和小程序的view类似. 通常我们在开发小程序(从列表页跳转到详情页)通过富文本 ...

随机推荐

  1. [js高手之路]html5 canvas动画教程 - 跟着鼠标移动消失的一堆炫彩小球

    综合利用前面所学,实现一个绚丽的小球动画,这个实例用到的知识点,在我的博客全部都有,可以去这里查看所有的canvas教程 <head> <meta charset='utf-8' / ...

  2. shell中的循环语句while

    循环语句的结构: ------------| while 条件        | do | 需要执行的命令   | done  | -----------| 例如: 1.while一直循环 2.whi ...

  3. Android语音识别--->>RecongnizerIntent实现

    首先,咱得先说下注意点: Android中主要通过RecognizerIntent来实现语音识别,其实代码比较简单,但是如果找不到设置,就会抛出异常 ActivityNotFoundException ...

  4. 使用js对form表单base64加密

    利用js可以对前台数据加密,以防止被恶意获取,以下代码,用base64对数据进行加密,可以在后台进行解密. 引入的js <script type="text/javascript&qu ...

  5. Mistakes in Hello World

    今天在cmd中用Python写第一行代码"Hello World"出现错误. 写好的源码"HelloWorld.py"存放于" F:\learning ...

  6. Android基础_web通信

    一.发展史 1G 模拟制式手机,只能进行语音通话2G 数字制式手机,增加接收数据等功能3G 智能手机,它已经成了集语音通信和多媒体通信相结合,并且包括图像.音乐.网页浏览.电话会议以及其它一些信息服务 ...

  7. 一步一步创建ASP.NET MVC5程序[Repository+Autofac+Automapper+SqlSugar](五)

    前言 Hi,大家好,我是Rector 时间飞逝,一个星期又过去了,今天还是星期五,Rector在图享网继续跟大家分享系列文本:一步一步创建ASP.NET MVC5程序[Repository+Autof ...

  8. Python中的数据类型以及他们的方法

    数据类型: 1)int i = 100 print(i.bit_length()) ''' bit_length 1 0000 0001 1 2 0000 0010 2 3 0000 0011 2 2 ...

  9. HashMap 源码详细分析(JDK1.8)

    一.概述 本篇文章我们来聊聊大家日常开发中常用的一个集合类 - HashMap.HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现.HashMap 允许 null 键和 null 值, ...

  10. poj 3294

    Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 12688   Accepted: 3552 Descr ...