2020年6月,腾讯的分布式数据库tbase 2.1版开源([1])。

腾讯在参考资料[1]的开头说明“TBase is an advanced enterprise-level database management system based on prior work of Postgres-XL project”,这是很不错的,体现了开源的精神。
下面对这一数据库与它的前身 Postgres-XL[2]做一比较。
1.安装
1.1 tbase源代码安装

tbase的最新发版的源代码位于(https://github.com/Tencent/TBase/archive/v2.1.0.tar.gz)
而随时更新的源代码主存储库位于(https://github.com/Tencent/TBase/archive/master.zip),为了下面的测试内容和过程可重复,有参考和比较价值,这里采用稳定的发版源代码。

参考资料[1]的内容比较简略,不适合于没有经验的人,我在上面就遇到了好几个问题,在tbase技术支持专家的指导下,用了几天反复试验才解决。

参考资料[1]上的详细资料位于https://github.com/Tencent/TBase/wiki。这个页面还贴心地贴出了支持团队的微信二维码,可以为用户提供及时的技术支持。
上面的文章列表如下,除了前二篇是英文资料,其余都是中文汉字资料,这对我们中国用户是很方便的。
0、TBase_Quick_Start.EN
0、TBase_Use_Articles.EN
1、TBase_Quick_Start
2、TBase基本使用篇
3、TBase高级使用篇
4、TBase应用接入指南
5、TBase组件安装及管理
6、TBase主备切换
7、TBase用户权限管理
8、TBase数据导入导出
9、TBase使用问题定位及性能优化

下面仍然用参考资料[1]的步骤来安装。

第一部分Building的步骤看起来没有太多问题,稍有linux/unix经验的人都知道SOURCECODE_PATH和INSTALL_PATH是需要设置的环境变量,而如何解压tar.gz压缩包也是完全可以从其他资料查阅的。
cd ${SOURCECODE_PATH}
rm -rf ${INSTALL_PATH}/tbase_bin_v2.0
chmod +x configure*
./configure --prefix=${INSTALL_PATH}/tbase_bin_v2.0 --enable-user-switch --with-openssl --with-ossp-uuid CFLAGS=-g
make clean
make -sj
make install
chmod +x contrib/pgxc_ctl/make_signature
cd contrib
make -sj
make install

但是,等到实际操作就会发现,这第3行是不容易一次成功的,问题在于,它没有说明安装的前提条件和依赖包。例如,在我的机器上,第一次运行在如下地方中断了
checking for library containing readline... no
configure: error: readline library not found
If you have readline already installed, see config.log for details on the
failure.  It is possible the compiler isn't looking in the proper directory.
Use --without-readline to disable readline support.
使用上述提示的--without-readline选项来继续安装,又会报以下错误,
checking for inflate in -lz... no
configure: error: zlib library not found
If you have zlib already installed, see config.log for details on the
failure.  It is possible the compiler isn't looking in the proper directory.
Use --without-zlib to disable zlib support.

checking for CRYPTO_new_ex_data in -lcrypto... no
configure: error: library 'crypto' is required for OpenSSL
等等。
而且有些包是必须的,不能采用--without的选项忽略。
经查阅网上资料,采用下面的命令安装了readline依赖包。
yum install readline readline-devel
再安装openssl依赖包。
yum install openssl openssl-devel


文档本来完全可以说明这一点,并给出一个完整的依赖包安装命令,方便用户继续从tbase源代码安装,如参考资料[3]所示:
yum install openssl openssl-devel pam pam-devel libxml2 libxml2-devel libxslt libxslt-devel perl perl-devel python-devel \
    perl-ExtUtils-Embed readline readline-devel  zlib zlib-devel gettext gettext-devel bison flex

这个步骤有个地方值得表扬,make -sj命令使用多线程静默方式编译,消除了大量的编译命令显示和输出,还提高了编译速度。

编译完成后,${INSTALL_PATH}/tbase_bin_v2.0目录下产生了bin、include、lib、share 4个
目录,需要将其复制到将来实际安装tbase的目录,注意是复制而不是移动,因为用pgxc_ctl部署失败有可能会删除二进制文件,我就被迫再次编译了,这里文档也没有提及。

第二部分Installation的安装步骤首先要配置环境变量
把tbase用户主目录下的.bashrc资源文件修改为

-bash-4.2$ cat .bashrc
# .bashrc

# Source global definitions
if [ -f /etc/bashrc ]; then
        . /etc/bashrc
fi
PG_HOME=/data/tbase/install/tbase_bin_v2.0
export PATH="$PATH:$PG_HOME/bin"
export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$PG_HOME/lib"
export LC_ALL=C
export TMPDIR=/data/tbase/tmp/
export PGHOST=a.a.a.a

其中TMPDIR的指定很重要,很重要,很重要,否则在执行过程中,会找不到临时目录,出现类似下面的错误,而参考资料[1]没有提及这个问题。
sh: -c: line 0: syntax error near unexpected token `('
sh: -c: line 0: `( tar czCf (null) (null)/657023.tgz bin include lib share ) < /dev/null > (null)/STDOUT_657023_0 2>&1'
ERROR: Cannot open "(null)/STDOUT_657023_0" for read, No such file or directory

在我的linux版本上,用户登录时实际调用的是.bash_profile
所以如果由于某种原因系统中缺少这个文件,要编辑如下内容:
[tbase@a.a.a.a ~]$ cat  .bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

然后修改~/pgxc_ctl/pgxc_ctl.conf配置文件。

pgxcInstallDir=${INSTALL_PATH}/tbase_bin_v2.0
GTM, 需要配置节点名、 IP端口和节点目录。
#---- GTM ----------
gtmName=gtm
gtmMasterServer=xxx.xxx.xxx.1
gtmMasterPort=50001
gtmMasterDir=${GTM_MASTER_DATA_DIR}/data/gtm_master
If you do not need gtmSlave, you can directly set it to 'n' in the configuration of the corresponding node.
gtmSlave=n
GTM从节点不需要就不用填了。
协调节点同样
coordNames=(cn001)
coordMasterCluster=(tbase_cluster)
coordPorts=(30004)
poolerPorts=(30014)
coordPgHbaEntries=(0.0.0.0/0)
coordMasterServers=(xxx.xxx.xxx.2)
coordMasterDirs=(${COORD_MASTER_DATA_DIR}/data/cn_master/cn001)
数据节点,这里实际可以采用一个地址,但需要配两个不同的端口
primaryDatanode=dn001
datanodeNames=(dn001 dn002)
datanodePorts=(20008 20009)
datanodePoolerPorts=(20018 20019)
datanodeMasterCluster=(tbase_cluster tbase_cluster)
datanodePgHbaEntries=(0.0.0.0/0)
datanodeMasterServers=(xxx.xxx.xxx.3 xxx.xxx.xxx.4)
datanodeMasterDirs=(${DATANODE_MASTER_DATA_DIR}/data/dn_master/dn001 ${DATANODE_MASTER_DATA_DIR}/data/dn_master/dn002)

如果直接编辑了这个文件,然后运行pgxc_ctl,会有很多错误信息,无法完成操作。
[tbase@a.a.a.a ~]$ pgxc_ctl
/bin/bash
Installing pgxc_ctl_bash script as /home/tbase/pgxc_ctl/pgxc_ctl_bash.
Installing pgxc_ctl_bash script as /home/tbase/pgxc_ctl/pgxc_ctl_bash.
Reading configuration using /home/tbase/pgxc_ctl/pgxc_ctl_bash --home /home/tbase/pgxc_ctl --configuration /home/tbase/pgxc_ctl/pgxc_ctl.conf
Finished reading configuration.
ERROR: Number of elements in coordinator master definitions are different coordNames and coordMaxWALSenders.  Check your configuration
ERROR: Number of elements in datanode master definitions are different datanodeNames and datanodeMaxWALSenders.  Check your configuration
ERROR: Found fundamental configuration error.

而参考资料[1]写的“After the pgxc_ctl tool is started, a template of pgxc_ctl directory and configuration file will be generated in the current user's home directory”,其实也不正确。
运行pgxc_ctl工具并未产生模板文件。

配置文件对于新手是有难度的工作,tbase支持人员推荐我学习wiki目录中的《5、TBase组件安装及管理》以及《1、TBase_Quick_Start》文档。
为了加快安装过程,技术支持专家为我提供了一个她做好的pgxc_ctl.conf配置文件模板,我只要修改ip地址就足够了。
这里最大的一个坑正是ip地址,由于我用来安装的主机具有106打头的外网地址,可以远程登录,而用ifconfig查不到这个地址,查到的地址是172打头的内网地址,下面简称a.a.a.a。
我一开始不了解情况,替换技术支持专家提供的pgxc_ctl.conf配置文件时,所有地址均采用了106打头的地址,各种操作极慢,但却没有报错。
[tbase@a.a.a.a pgxc_ctl]$ pgxc_ctl
/bin/bash
Installing pgxc_ctl_bash script as /home/tbase/pgxc_ctl/pgxc_ctl_bash.
Installing pgxc_ctl_bash script as /home/tbase/pgxc_ctl/pgxc_ctl_bash.
Reading configuration using /home/tbase/pgxc_ctl/pgxc_ctl_bash --home /home/tbase/pgxc_ctl --configuration /home/tbase/pgxc_ctl/pgxc_ctl.conf
Finished reading configuration.
   ******** PGXC_CTL START ***************

Current directory: /home/tbase/pgxc_ctl
PGXC deploy all
Deploying Postgres-XL components to all the target servers.
Prepare tarball to deploy ...
这实际上是把文件复制到各节点。设置ssh等效的原因就是为了复制过程不需要输入其他主机的口令。其实对于单机,deploy all操作是多余的,因为各个节点实际上都是同一个路径,无需把可执行文件复制过去。
deploy all完成后,再在PGXC 提示符下输入
init all
启动过程中会出现各种异常信息,可以用提示中的方法解决。

比如:LOG:  skipping missing configuration file "/data/tbase/global/global_tbase.conf"
其中保存的是各种全局参数,可以在相应目录编辑类似以下内容。
max_wal_senders=32
shared_buffers = 2GB
unix_socket_directories='/data/tbase/tmp/'
还有下面的警告信息,
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.
要在每个协调和数据节点目录中的pg_hba.conf文件中添加一行
host all tbase a.a.a.a/32 trust
然后重新启动集群
安装完成后,只能用127.0.0.1本地地址访问,而不能用我在pgxc_ctl.conf配置文件中指定的地址访问。
用psql客户端连接,
[tbase@a.a.a.a bin]$ psql postgres -h 127.0.0.1  -p 30004 -U tbase

postgres=# select 1;
长时间卡住。
最后报错:
ERROR:  GTM error, could not obtain global timestamp. Current XID = 0, Autovac = 0
查看gtm日志也没有找到原因。

请教技术支持专家后,她说pgxc_ctl.conf配置文件中应该填写内网地址。
替换完成后,所有的命令执行速度都极大地提高了,以前各种操作的慢估计都是在等待超时。
现在集群登录后可以执行一些查询了。
[tbase@a.a.a.a bin]$ /data/tbase/install/tbase_bin_v2.0/bin/psql -h   a.a.a.a    -p 30004 -U tbase -d postgres
psql (PostgreSQL 10.0 TBase V2)
Type "help" for help.

postgres=# select version();
                                                     version
------------------------------------------------------------------------------------------------------------------
 PostgreSQL 10.0 TBase V2 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-39), 64-bit

这里有个缺陷,源代码说明是2.1版,查看版本信息仍然是2.0版。

postgres=# select 1;
 ?column?
----------
        1
(1 row)

postgres=# SELECT * FROM pgxc_node;
 node_name | node_type | node_port |  node_host  | nodeis_primary | nodeis_preferred |  node_id   | node_cluster_name
-----------+-----------+-----------+-------------+----------------+------------------+------------+-------------------
 gtm       | G         |     50001 |   a.a.a.a   | t              | f                |  428125959 | tbase_cluster
 cn001     | C         |     30004 |   a.a.a.a   | f              | f                | -264077367 | tbase_cluster
 dn001     | D         |     40004 |   a.a.a.a   | t              | t                | 2142761564 | tbase_cluster
 dn002     | D         |     40005 |   a.a.a.a   | f              | t                |  -17499968 | tbase_cluster
(4 rows)
与postgres-xl的区别是,有一行gtm的内容。
但是配置还未完成,仍然无法建立数据库和表,集群还不能使用,create database超时报错,其他操作类似。
postgres=# create database test LC_COLLATE='zh_CN.UTF-8' LC_CTYPE='zh_CN.UTF-8' encoding 'utf8'template template0;
ERROR:  Failed to get pooled connections
HINT:  This may happen because one or more nodes are currently unreachable, either because of node or network failure.
 Its also possible that the target node may have hit the connection limit or the pooler is configured with low connections.
 Please check if all nodes are running fine and also review max_connections and max_pool_size configuration parameters


原来~/.bashrc里还有一个PGHOST=ip地址,改过来以后,进入pgxc_ctl工具界面,stop all再start all, 现在create database立刻报错:
postgres=# create database test LC_COLLATE='zh_CN.UTF-8' LC_CTYPE='zh_CN.UTF-8' encoding 'utf8'template template0;
ERROR:  pgxc_node_set_query: nodename:dn002,backend_pid:1413946,message:node "cn001_1413921" does not exist,detail:,hint:

再次进入pgxc_ctl工具界面,clean all再init all,再次登录,可以建立数据库,环境配置好了。
所以各种问题的原因就是ip,几个配置文件中的每一处都要改为ifconfig查找到的实际地址,数据库集群才能使用。
后面就用此版本来做功能测试。

参考资料[1]还有一个问题是最后二步输入的命令不明显,虽然给出了截图,还是不如直接用明显的代码文本显示。

其实,PGXC提示符下输入help可以得到比较简明的命令用法,比如monitor可以监控各种节点。
PGXC help
You are using pgxc_ctl, the configuration utility for PGXL
Type:
    help <command>
    where <command> is either add, Createdb, Createuser, clean,
        configure, deploy, failover, init, kill, log, monitor,
        prepare, q, reconnect, remove, set, show, start,
        stop or unregister
PGXC help monitor

monitor all
monitor nodename ...
monitor gtm [ master | slave | all ]
monitor gtm_proxy [ all | nodename ... ]
monitor coordinator nodename ...
monitor coordinator [ master | slave ] [ all | nodename ... ]
monitor datanode nodename ...
monitor datanode [ master | slave ] [ all | nodename ...  ]

Monitors if specified nodes are running
For more details, please see the pgxc_ctl documentation

add命令用于添加各种节点
PGXC help add

add gtm slave slave_name host port dir
add gtm_proxy name host port dir
add coordinator master name host port pooler dir extra_conf extra_pghba
add coordinator slave name host port pooler dir archDir
add datanode master name host port pooler dir xlogdir restore_datanode_name extra_conf extra_pghba
add datanode slave name host port pooler dir xlogdir archDir

Add the specified node to your postgres-xl cluster:
For more details, please see the pgxc_ctl documentation

PGXC add gtm master gtm a.a.a.a 50001 /data/tbase/g/data/gtm_master
这样执行的结果会产生一个包含一个gtm配置信息的pgxc_ctl.conf文件。
总之,工具是有用的,关键是要用对。
下面postgres-xl安装过程中,将会用到其中的一些命令。

1.2 postgres-xl源代码安装
tbase的最新发版的源代码位于(https://www.postgres-xl.org/downloads/postgres-xl-10r1.1.tar.gz)。
发布日期是2019-02-18,最近一年都没有新版本发布。
https://www.postgres-xl.org/download/中提供的
安装步骤同样过于简略,不过从文档目录中翻阅发现了下面一个堪称典范的文本,tbase也许正缺少这么一个适用于完全没有经验的人的文档。
https://www.postgres-xl.org/documentation/install-short.html
这前三行解释了为什么它对于入门非常合适。
The following short installation allows to install a simple cluster on a local machine with 1 Coordinator, 2 Datanodes and 1 GTM.
在单机上搭建一个包含一个协调节点、二个数据节点(一个节点不足以体验分布式功能)、一个全局事务管理节点的集群。极其低的硬件门槛和最简化的拓扑结构,导致最短时间内可以上手。实际上,我在tbase的
github站点上提的第一个问题也就是这个。

When installing a more complex cluster, you might change the number of Coordinators and Datanodes, and might have to start nodes on different servers. 
这行告诉我们更复杂的集群包含更多的节点,以及部署在不同的机器上。
Also, you can instead use the pgxc_ctl utility, which simplifies the installation and configuration process.
这行告诉我们可以用工具来简化安装和配置,而不是直接上来就用工具,掩盖了后台操作的同时,也使排除故障变得艰难。实际上,tbase支持人员推荐我学习的《TBase组件安装及管理》文档的内容与此类似。
然后就是直截了当的命令行,只要逐一复制就能执行,没有复杂的编辑配置文件保存的步骤,每一步的输出的含义都是明确的。

除了开头几行有些内容稍显过时,比如没有采取并行编译,其余都是不分版本通用的。下面简单注释如下:
#配置和编译
./configure
gmake
su
gmake install
#创建用户和目录,并授权
adduser postgres
mkdir /usr/local/pgsql/data_coord1
mkdir /usr/local/pgsql/data_datanode_1
mkdir /usr/local/pgsql/data_datanode_2
mkdir /usr/local/pgsql/data_gtm
chown postgres /usr/local/pgsql/data_coord1
chown postgres /usr/local/pgsql/data_datanode_1
chown postgres /usr/local/pgsql/data_datanode_2
chown postgres /usr/local/pgsql/data_gtm
#初始化数据库
su - postgres
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data_coord1 \
  --nodename coord1
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data_datanode_1 \
  --nodename datanode_1
/usr/local/pgsql/bin/initdb -D /usr/local/pgsql/data_datanode_2 \
  --nodename datanode_2
#初始化GTM并启动服务
/usr/local/pgsql/bin/initgtm -D /usr/local/pgsql/data_gtm -Z gtm
/usr/local/pgsql/bin/gtm -D /usr/local/pgsql/data_gtm >logfile 2>&1 &
#启动节点服务,指定端口
/usr/local/pgsql/bin/postgres --datanode -p 15432 -c pooler_port=40101 \
  -D /usr/local/pgsql/data_datanode_1 >logfile 2>&1 &
/usr/local/pgsql/bin/postgres --datanode -p 15433 -c pooler_port=40102 \
  -D /usr/local/pgsql/data_datanode_2 >logfile 2>&1 &
/usr/local/pgsql/bin/postgres --coordinator -c pooler_port=40100 \
  -D /usr/local/pgsql/data_coord1 >logfile 2>&1 &
#在数据库中添加节点信息
/usr/local/pgsql/bin/psql -c "ALTER NODE coord1 \
  WITH (TYPE = 'coordinator', PORT = 5432)" postgres
/usr/local/pgsql/bin/psql -c "CREATE NODE datanode_1 \
  WITH (TYPE = 'datanode', PORT = 15432)" postgres
/usr/local/pgsql/bin/psql -c "CREATE NODE datanode_2 \
  WITH (TYPE = 'datanode', PORT = 15433)" postgres

/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_1) \
  'ALTER NODE datanode_1 WITH (TYPE = ''datanode'', PORT = 15432)'" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_1) \
  'CREATE NODE datanode_2 WITH (TYPE = ''datanode'', PORT = 15433)'" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_1) \
  'CREATE NODE coord1 WITH (TYPE = ''coordinator'', PORT = 5432)'" postgres

/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_2) \
  'ALTER NODE datanode_2 WITH (TYPE = ''datanode'', PORT = 15433)'" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_2) \
  'CREATE NODE datanode_1 WITH (TYPE = ''datanode'', PORT = 15432)'" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_2) \
  'CREATE NODE coord1 WITH (TYPE = ''coordinator'', PORT = 5432)'" postgres
#检查集群
/usr/local/pgsql/bin/psql -c "SELECT pgxc_pool_reload()" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_1) \
  'SELECT pgxc_pool_reload()'" postgres
/usr/local/pgsql/bin/psql -c "EXECUTE DIRECT ON (datanode_2) \
  'SELECT pgxc_pool_reload()'" postgres
#建新测试数据库并连接
/usr/local/pgsql/bin/createdb test
/usr/local/pgsql/bin/psql test

做完这几步以后就可以输入SQL查看集群的节点了。没有任何与网络相关的操作。
test=# SELECT * FROM pgxc_node;
 node_name  | node_type | node_port | node_host | nodeis_primary | nodeis_preferred |   node_id
------------+-----------+-----------+-----------+----------------+------------------+-------------
 coord1     | C         |      5432 | localhost | f              | f                |  1885696643
 datanode_1 | D         |     15432 | localhost | f              | f                |  -675012441
 datanode_2 | D         |     15433 | localhost | f              | f                | -1047623914
(3 rows)
这个版本下面会弃用,因为要用pgxc_ctl 工具重新做一个集群。
但顺畅的安装过程(编译的顺畅要归功于安装tbase时安装的依赖包)确实给用户带来很大的满足感,从而对此软件产生了好感。
[1]https://github.com/Tencent/TBase
[2]https://www.postgres-xl.org/
[3]PostgreSQL源码安装及配置(http://www.freeoa.net/osuport/db/postgresql-source-compile-install-config_3141.html)