开发者学堂课程【PolarDB for PostgreSQL 内核解读系列课程:【视频】PostgreSQL 系统概述】学习笔记(二),与课程紧密连接,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/1042/detail/15199
【视频】PostgreSQL系统概述
内容介绍
一.课程目标及策略
二.PostgreSQL 概述(历史、架构)
三.PostgreSQL 安装启动
四.PostgreSQL 常用命令、调试
五.总结
四.PostgreSQL 常用命令、调试
使用 psql 连接数据库
psql连接一个数据库,create table创建一个表插入信息,之后再查出来。Psql里面有很多一些简化的快捷能力,比方说List view,-DV,list database。如果不用这个东西也能通过系统表取代它系统表格里面的信息给查出来,但是查的话比较麻烦,所以一般会利用一些快捷方式。
演示一下相关的一些命令,这些命令都在boundary的目录下面,有很多命令,最后会介绍怎么去调试,比方说这里边怎么用pstack去对战,怎么去用gdb去跟踪,跟踪过程中有哪些命令是常用的,跟大家一起跟踪东西看一下。
开发工具-source insight
开发工具讲解内容主要用的是source insight工具,它的好处是左右的两个屏幕分别都有前进后退,注意别把代码看错。左面的relicion窗口比较好,函数在查的时候谁调用他可以知道,而另一个函数又是谁调用的也能打开看到。相对来说,很难知道有哪些人去调用过他,如果每次都是去search就很麻烦。所以有这样的视图是非常好用的,很多的ide是不具备的。
右下角有一个符号的查询,输入符号,包括文件的查询,目录的情况都可以看。
后面这几部分还是实操一下,如果光这么讲可能大家也没感觉,原则是每一条命令尽量都运行一下。
git clone https://aithub.com/postgres/postgres.ait
cd postgres
git branch -r|grep -v '\->'| while read remote; do git branch--track "${remote#origin/}" "$remote"; done
git fetch --all
git pull -all
git branch
git checkout REL_11_STABLE
运行git命令之后呢,就会得到这个源码,得到源码以后可以看到通过刚才的这几条命令就把所有的branch拿过来,查git branch有一部分是有的,需要git checkout,得到想要的pg11的这个版本。因为主要还是用pg11的比较稳定的版本,虽然已经有几年了,但是这个大家用的还是比较多的。
下面看一下config配置的过程,大家看一下它的help就知道这里面enable-debug和enable-dtrace是什么意思,看一下library怎么包含的,这里其实介绍的比较清楚。如果大家对参数不清楚,也可以来看一下英文的帮助。现在要调用config的一个debug的版本,就调用这条命令:
./configure--prefix=/home/michael.yw/pghome--enable-debug--enable-cassert CFLAGS="-ggd db -00-g3-Wall -fno-omit-frame-pointer-fstack-protector-strong"
先make clean一下,把之前编辑的内容清理干净,不会对这次有影响。调用config这个相关的方法的debug版本,这个过程中就调用他的config的相关文件。config完了以后,调用make -sj && make install进行编译还有git的安装:
前面步骤是没有报错的。之后会因为S这个参数,它是静默的意思,不会弹很多信息或者信息会比较少,安装的过程会显示已经安装完成,做了很多拷贝的动作,会把它放到相关的目录下。可以看一下pghome目录,这个目录里有一些刚才新安装的一些文件。之后需要调用这个系统的环境变量,环境变量就是把这几行拷过来:export PATH="/home/michael.yw/pghome/bin:$PATH"
export_LD_LIBRARY_PATH="/home/michael.yw/pghome/lib:$LD_LIBRARY_PATH
export_PGHOME="/home/michael.yw/pghome
export PGDATA="/home/michael.yw/pgdata
这里注意一下,这个目录是在老师的home下面,老师的用户名叫Michael YW,所以这个肯定是要改的,后面的其他部分不用改也可以,或者有自己的一些位置想放都没问题。包括前面的前缀往哪个地方安装,位置也是要在这边指定的。
把这个文件拷过来保存一下,就可以利用source命令让它立即生效,生效以后,相当于环境变量配置成功。下面利用initdb来初始化数据库。
初始化数据库,可以看到这个位置已经有上次安装的数据,可以先用ps命令去查看一下原来那个进程是否已经关闭了,下面要做的是把原来的老的数据库删掉,使之完全没有影响。下面要用initdb这个命令创建数据库的目录,创建完以后看到按照刚才说的几个步骤都有,最终要启动要按照步骤启动。pgdata里都是最新的一些数据,有了最新的数据以后,需要去参数配置。
把这个参数拷过来:
maxconnections=100 max_wal_senders=10
max_replication_slots=10 max_worker_processes=10
shared_preload_libraries='pg_statstatements listen_addresses='* port=6688
logging_collector=on log_directory='log
log_filename=postgresql-%a.log log truncate_onrotation=on log_rotation_age=1d log_rotation_size=0 log_checkpoints=on log_connections=on log_disconnections=on
log error verbosity=verbose log_line_prefix='%m[%p] log_timezone='PRC'
log_autovacuum_min_duration=0
把参数文件打开,翻到最下面,把参数插到后面的位置。这是新的配置,配置最重要的端口6688,记住后面要连接的都是这个端口。这个参数配置完以后,要启动。调用这个命令是首先会-D,指定data目录,刚才初始化的时候使用同一个目录,这时可以在这里加一个日志文件,启动。显示server start意思是启动成功。查找之后发现多了一些与postgres相关的进程。
最上面的postgre这个进程是post master进程,他的进程号931。后面的进程可以看到他们的父进程都是931,就说明他们是postmaster发出的一些子进程。
下面看一常用的命令。用psql连接post master,在启动的时候,它的配置文件监听6688这个端口,如果要是去连接6688端口,就能找到POS的这个进程,因为他俩是同一台机器不用指定IP,否则需要指定IP才能找到IP地址下的688端口,就可以连到他。连上之后就可以发一些请求,
发请求的时候创建一个表:create table t1(a int, b text);
成功之后再插入一条数据:insert into t1 values(1, 'aa');
成功之后再查询一条数据:select * from t1;
也成功了。演示主要想先创建替换这张表后面可能会用到,这里再演示一下psql有一些快捷命令,大家可以看一下:
这里可以看一下list table 、list view,把这个例子对应的table就会显示出来。刚才创建的表就显示出来了。其他的快捷键也都是为了帮助快捷的实现查询的,本来这些数据都是存在系统表里,它通常会用cache把系统表里的数据提前缓存到内存里。在查询的过程中,是在内存里把数据查出来的一个过程。
PG 常用命令及调试
先进到这个目录下:cd/home/michael.yw/pghome/bin
常用命令包括创建、DB、刚才用到的initdb、config等等。刚才设的那些很重要的变量,它的内部有没有识别到。因为有的时候出错是因为环境没设对,为什么没对呢?就可以通过这个看一下这里可能有的时候路径可设错了,这个可以帮你去找一些启动时的错误。
比方说PQ、Postgres进程、pg ctl。pg ctl大家都知道很重要,刚才也提到了,global里有control文件,文件记录的是他的信息,比方说日志文件,位置、系统的一些状态、是不是正在运行或者系统启动的一些次数等等细节都在这里。系统最开始依此来进行恢复,恢复的时候首先得知道原来的位置,所以位置等细节都在这里进行记录,这个文件是非常重要的。所以在做开发的时候,以前会针对这个文件做很多保护防止它坏掉。比如会做两份,轮番来写这样的一些操作。
createdb也在这个目录下,他就可以创建一个新的数据库,连接也是先连接6688端口,指定数据库的名字。
通过pg_dump连接6688端口,之后指定数据库和它对应的一个表,进行一个导出。导出到t1.sql,没指定目录,就再当前的目录下。看一下t1.sql是什么呢?
首先把表元数据结构创建出来,Alert一下这个相关的owner,变成michael yw之后再进行一些数据,刚才传入的11和aa数据,拷贝到表里,这就是一个导出的过程,再导入到其他的数据库里,用restore命令给导入回去。
[michael.yw@i22g03178.eu95sqa/home/michael.yw]$11 ll
total 52
drwxr-xr-x 9 michael.yw users 4096 Jun 6 10:12 bak
drwxr-xr-x 4 michael.yw users 4096 Dec 17 2020 bdrdata
drwxr-xr-x 2 michael.yw users 4096 Mar 1 2021 core
drwxr-xr-x 3 michael.yw users 4096 May 21 2021 DATA
drwxr-xr-x 3 michael.yw users 4096 Dec 16 2020 download
drwxr-xr-x5 michael.yw users 4096 Nov 252021 myenv
drwx------20 michael.yw users 4096 Jun 23 21:17 pgdata
drwxr-xr-x 6 michael.yw users 4096 Jun 6 10:18 pghome
drwxr-xr-x 3 michael.yw users 4096 Jul 14 2021 pgxc_ctl
drwxr-xr-x 4 michael yw users 4096 Aug 16 2021 polardb
drwxr-xr-x 10 michael.yw users 4096 Jun 2 11:43 PolarDB-for-PostgreSQL
drwxr-xr-x 7 michael.yw users 4096 Jun 23 20:21 postgres
lrwxrwxrwx 1 michael.yw users 16 Nov 30 2021 u01 -> /u01/michael.yw/
drwxr-xr-x 9 michael yw users 4096 Jul 20 2021 xpgdata
再打开另一个窗口,这个窗口也是这台机器,去进行一个几率调试。首先先看一下,这个进程跟刚才是不一样的,多了一个psql,psql运行起来以后就多了这么一个进程。另外会有postgre sql,就是前面讲到的backend进程是为了这个psql连到了post master上,post master说需要提供服务,就fog出一个新的backend进程为他提供服务。
可以看一下pstack是最简单的对战的情况。首先这个进程从附近调它的对战很简单,是postmastermain,进来以后,不停的serverloop,不停的在监听, 6688端口如果有人连了,这个时候就会启动一个新的进程给他提供服务。
这个进程是对外提供服务的进程,是一个postgres的backend的进程,它不停地在readcommand,readcommand的意思是“我跟你已经建立连接“,联系以后就不停的在循环去等待他给他传一些新的信息,比方说要查询某个数据的时候,先来读它这个信息,所以readcommand是去读有没有新的输入
下面看一下GDB。首先GDB的这个用法, gdb加上进程名字,如果要是没有指定环境变量,需要把整个名字给他写过来,包括全路径。加了这个名字之后指定一下要跟踪的pid,这样其实就是一个跟踪的过程,跟踪的时候bt一下就可以看到这里的堆栈跟pstack看到的是一样的。但是它的好处是可以去切换,比如切换f8,这个就相当于他对战里面的第八层。
第八层把代码显示出来了,在这个地方read command,最后就会跳到第七层,最后慢慢的不停的read命令。这个时候如果用C+xa-就可以介入到查看代码的窗口。这个窗口在调试的时候更方便,能显示更多的代码,相当于代码的一个可视化方法,有了这个之后调试,需要设置一个断点,那个断点是叫执行sql query, b-b的b就是设置断点,成功以后,设置第一个断点,是在下面这个文件里的915行设置了断点。
multi-thre Thread 0x7f5a9 In: PostgresMain(gdb) b exec_simple_query
Breakpoint 1 at 0x8f06fa: file postgres.c,line 915.(gdb)1
设置断点以后就会查一下这个断点,Info b显示断点,查看断点就是比如设多了可以delete一些断点。查到这个断点在这个里面已经设置好了,设置好断点以后就开始正式的调试。
调试的时候模拟用户给他发一个请求,正常来说请求发完之后,它就会把查询的结果显示出来,但是目前看是没有任何显示的。为什么没有显示呢?是因为现在设置了一个断点,它进入到这个断点里了。所以这边先按c这个命令,这样就能跳到现在断点的这个位置上,相当于执行到断点的位置。
下面就跟踪,BT看一下他的堆栈是从上一级调回来的,F1,切换到上一个堆栈,上一个堆栈为什么会进这里呢?从头看这个函数postgres的loop,首先是postscript in的这个函数,这个函数做了一个循环的处理,就是在不停地等待,它连接的用户给他提供sql的请求,所以这里看不停的在read command,那read command现在的情况是已经read成功了,否则它就一直在read command,现在已经相当于跳到执行的断点里,它已经读到了发送的命令。
这时需要根据协议去看select命令到底用哪个分支来处理。这个分支叫Q消息,后面会有这个P消息,B消息,E消息:
E一般存储过程会用到,prepare之后进行绑定一些参数,再在存储过程里面去执行。所以这个叫PBE。一般select这些简单的sql,是simple query里去做的,而Q消息这些消息是封装了一些apq的一些消息。这些消息便于两边apq协议来进行一些交互,这其实是一些网络协议的定义。
继续来跟踪, F1回到F0,还是从这个位置开始,看看之后它会执行什么。首先要执行simple query,query的string已经得到了。之后走下一条,继续往下跟踪,如果还是要n,直接回车即可。它启动了一个事物来做这个事情,之后这里面切换memorycontext,memorycontext后面会讲到,主要和存储引擎有些关系。后面它进到parser里,把字符串解析成一个parsetree的树状格式,继续进入到后面的这些解析的过程。
snapshot会根据隔离级别形成snapshot。rewrite之后生成query tree,最终生成plantree这个过程,生成query tree和plantree的这个引擎后面也会讲到。
创建portal,portal相当于把SQL查询封装起来,封装起这里,比方说memorycontext等一些自己独立的东西,这些东西无论是回滚或者提交,都可以很容易的把一些资源释放掉,相当于把执行包了个壳。
portal类型也做一些定义。后面几个可以看到结果集的格式的近似值还有“发送“,怎么去发送结果集、包括参数的设置。之后就可以开始正常run了。portalrun,这时没用N,用的是S,进入到函数里边,因为这个函数很重要。S的时候呢,可以看到portalrun干什么事情。设置一些前面的参数,比方说resourceowner这些,后面都会讲到,现在不细讲了
这边会根据它的策略选择不同的执行方法,portalrunselect做一些简单的查询来做这个事情。测试策略进程执行,执行后会dropportal,整个志愿就全清理掉了。finish事物的command,相当于是事物有状态机,finish状态机的时候,相当于把事物提交掉,执行以后会做事务提交的过程。
提交的过程是非常复杂的,这里不着急看。到这之后相当于执行新模块已经执行完了,这个内容还是缓存状态,没有发出去。原来做过这个类似于事务的支持或者失败怎么retry,都是会涉及到这个。相对来说这个参数执行的结果先不发给客户端,只有点击ture的时候。但是也有其他情况,比方说数据量特别大,缓冲不过来,他会发给客户端。所以可以看到左边这边持续到现在还没有结果:
等他变为ture以后再执行,就会得到相关的数据,相当于得到一个执行结果。这个执行结果相当于刚才缓存了数据之后,现在允许他发送了,vpq会把这个数据从这个程序发到另一个程序下面,他负责把这个结果显示出来格式化的过程。这是调试的整个过程。
下面简单演示一下source insight。
左面可以对应哪些函数在里面,随便找一个函数,点击刷新,就可以显示谁引用了这个函数。比如说postgre的状态机引用、serverloop也引用怎么办呢?,先看一下这个怎么引用呢?serverloop如果checkpointerpid等于0了,要启动一下。
其他的几个里面也是类似情况做一些判断,来做一些不同场景下的启动的流程。它的好处是有些函数调用的地方非常多,如果都用search就很麻烦,但是用这个方法点一下就可以看到所有与它相关的调用,而且可以查到谁又调用了它,这样依赖关系就会比较清楚。
可以查一些函数postgres:没加载出来因为太卡死机了。
中间的两个窗口都可以前进后退,这样就会很容易查看小文件的情况。
代码用这个工具会比较多一点,大家可以熟悉一下这个工具,source insight是比较老实的工具,尤其在Windows上用的比较多。相对来说DeepCoder是比较新的一个微软出的工具,这个工具的好处是pension、Java看起来都很方便。因特尔这个工具主要是porlar的ide来看的,这次的课程还是用Sourceinsight工具。可以下载熟悉一下怎么用的,下次代码进行跳转的时候就可以更容易的跟上。
五.总结
现在回顾一下这节课。这节课主要就是几个部分,第一部分讲总体的课程的一些设置。这个设置想告诉大家的主要就是两点,第一点是内容干货是很多的、详实的,包括存储引擎,知性引擎查询引擎事物,这都会有。
第二点想说的是如果看第一点,讲的内容也是挺多的。按照这个方法去学习的话,后面这些内容也都能掌握。今天整体的架构也学了,整体的目录包括数据目录和源码目录都看了。现在用同样的方法去操作一下,熟练了这部分也就算掌握了。所以下面也是一样的情况,我们都会先介绍它每个部分的架构和原理之后怎么操作的,最后才去讲代码,这个就比较简单了。之后讲一下它的历史,包括它的架构的一些情况、大家对目录的进程有一个大致的概念。
每个目录包括文件的格式的进程是什么样子的呢?后面课程都会涉及到的,所以这个也不用说一定要每个目录会了,那这个就不用学了。
这里要重点强调的是第三和第四部分。
这部分是整个课程的一个基础,大家课下一定要按照这个先安装部署一下,用他那个方法创建一个数据库启动起来。调试也练习一下,调试会了之后对后面学习也会有很大的帮助。
这个过程基本上没抄,按照拷贝一下就可以用了,很简单。大家都多练一练这部分,如果这部分搞定了下面就会事半功倍,欲善其事必先利其器。
有问题可以提,大家互相交流。