我们公司基于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. Hibernate学习笔记(4)---hibernate的核心接口

    Configuration类 该类主要是读取配置文件,启动hibernate,并负责管理hibernate的配置信息,一个程序只创建一个Configuration对象. Configuration类操 ...

  2. ts中interface与class的区别

    interface -- 接口只声明成员方法,不做实现. class -- 类声明并实现方法. 那么接口有什么用呢?设想如下需求: 要实现一个print函数,它将传入的对象打印出来.在实际实现上,它将 ...

  3. Excel生成guid、uuid

    1.Excel生成guid,uuid  格式:600d65bc-948a-1260-2217-fd8dfeebb1cd =LOWER(CONCATENATE(DEC2HEX(RANDBETWEEN(, ...

  4. js 抓取屏幕宽度设置字体大小 rem

    var doc = window.document var docEl = doc.documentElement var tid function refreshRem () { var width ...

  5. Babel 转码器 § es6转换es5

    Babel 转码器 § es6转换es5 实时转码 /  Repl  -babel-node / babel-register(自动转码引入babel-register模块) 配置文件.babelrc ...

  6. C#学习笔记-适配器模式

    什么是适配器模式? 适配器模式(Adapter):将一个类的接口转换成客户希望的另外一个接口. Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作. 什么时候运用适配器模式? ...

  7. zookeeper之分布式锁以及分布式计数器(通过curator框架实现)

    有人可能会问zookeeper我知道,但是curator是什么呢? 其实curator是apachede针对zookeeper开发的一个api框架是apache的顶级项目 他与zookeeper原生a ...

  8. flexbox 弹性盒子

    flexbox 弹性盒子 1.基本知识 container(容器)属性 flex-direction: row | row-reverse | column | column-reverse 属性决定 ...

  9. kafka快速入门(官方文档)

    第1步:下载代码 下载 1.0.0版本并解压缩. > tar -xzf kafka_2.11-1.0.0.tgz > cd kafka_2.11-1.0.0 第2步:启动服务器 Kafka ...

  10. [搬运] C# 这些年来受欢迎的特性

    原文地址:http://www.dotnetcurry.com/csharp/1411/csharp-favorite-features 在写这篇文章的时候,C# 已经有了 17 年的历史了,可以肯定 ...