Centos7 安装 Odoo11

Centos7 安装 Odoo111 安装python3.6Centos7 基于稳定性考虑安装的是python2.7,而且默认的官方 yum 源中不提供 Python 3 的安装包,所以我们要先换一个提供python3的yum源– IUS 。 1、IUS软件源依赖与epel软件源包,首先要安装epel软件源包sudo yum install epel-release2、安装IUS软件源sudo yum install https://centos7.iuscommunity.org/ius-release.rpm3、安装python3.6sudo yum install python36usudo yum -y install python36u-develsudo yum -y install python36u-pip2 安装配置PostgreSQL数据库2.1 安装1、安装sudo yum install -y postgresql-server2、初始化service postgresql initdb3、启动服务systemctl start postgresql4、设置开机运行服务systemctl enable postgresql2.2 配置1、创建数据库和角色# 切换到 postgres 用户sudo su - postgres# 登录PostgreSQL控制台psql# 系统提示符会变为"postgres=#",表示这时已经进入了数据库控制台# 创建数据库用户dbuserCREATE USER dbuser WITH PASSWORD ‘password’ ENCODING=‘UTF8’;# 创建用户数据库CREATE DATABASE exampledb OWNER dbuser;# 将exampledb数据库的所有权限都赋予dbuserGRANT ALL PRIVILEGES ON DATABASE exampledb to dbuser;# 使用\q命令退出控制台(也可以直接按ctrl+D)\q如果在创建数据库时报如下错误:ERROR: new encoding (UTF8) is incompatible with the encoding of the template database (SQL_ASCII)则通过如下方式解决update pg_database set datallowconn = TRUE where datname = ’template0’; \c template0update pg_database set datistemplate = FALSE where datname = ’template1’; drop database template1;create database template1 with encoding = ‘UTF8’ LC_CTYPE = ’en_US.UTF-8’ LC_COLLATE = ’en_US.UTF-8’ template = template0;update pg_database set datallowconn = TRUE where datname = ’template1’;\c template1update pg_database set datallowconn = FALSE where datname = ’template0’;——————— 作者:东方-phantom 来源:CSDN 原文:https://blog.csdn.net/hkyw000/article/details/52817422 版权声明:本文为博主原创文章,转载请附上博文链接!2、配置这一步要修改两个配置文件:pg_hba.conf 和 postgresql.conf 。可以通过以下命令找到文件位置:sudo find / -name ‘filename’首先修改 pg_hba.conf :添加下面这行(这行是用于可远程连接的,如果想限制数据库只能本地访问的话,跳过)host all all 0.0.0.0/0 md5找到并修改下面这两行local all all peer md5host all all 127.0.0.1/32 ident md5修改 postgresql.conf (用于可远程连接,如不需要可调过):添加下面这行listen_addresses = ‘*‘修改完成之后,重启服务:systemctl restart postgresql至此,PostgreSQL 安装配置完成!3 安装 node.js 和 less插件Odoo 前端依赖 node.js 和 less,用以下命令安装:sudo yum install -y nodejssudo npm install -g less less-plugin-clean-css4 安装依赖yum install wkhtmltopdfyum install python-devel openldap-develyum install libxslt-devel libxml++-devel libxml2-develyum install gcc5 安装Odoo11这里我们用 pipenv 安装,首先安装 pipenvpip3.6 install pipenv拉取odoo11 代码后,在项目根目录创建虚拟环境并安装依赖pipenv –python python3.6 install -r requirments.txt安装时会有一个 win32 的模块安装失败,不用管,这个是windows系统开发时需要依赖的包。安装完成之后,创建一个 odoo 配置文件: odoo.conf 。 内容如下:[options];模块路径addons_path = odoo/addons,odoo/myaddons;超级管理员密码admin_passwd = admindb_host = localhostdb_port = 5432db_maxconn = 64;数据库名称db_name = ***;数据库用户db_user = ***;数据库密码db_password = ***然后运行如下命令启动 odoopython odoo-bin -c odoo.conf访问 127.0.0.1:8069 ,如果进入到odoo登录页面就说明安装成功了! ...

January 31, 2019 · 2 min · jiezi

gdal扩展支持Excel与postgresql

最近做的项目有关数据的上传入库,涉及到空间数据的处理大部分从业人员第一反应都是想到用gdal来做,但是gdal默认支持的数据格式不包含xls和xlsx以及postgresql,因此需要我们自己安装拓展进行编译,为了能够复用,我把编译的整个过程写进了Dockerfile制作成了一个镜像,以此记录FROM centos:7.4.1708# 安装xls依赖库RUN yum groupinstall -y “Development Tools” && \ yum -y install wget && \ wget http://www.gaia-gis.it/gaia-sins/freexl-sources/freexl-1.0.5.tar.gz && \ tar -zvxf freexl-1.0.5.tar.gz && \ cd freexl-1.0.5 && \ ./configure && \ make -j 4 && \ make install# 安装GDAL的依赖库,这个都是可选的,其中expat-devel是支持excel扩展,postgresql-devel是pg的扩展RUN yum install -y sqlite-devel libxml2-devel swig expat-devel libcurl-devel libgeos-dev postgresql postgresql-devel && \ # 编译GDAL wget http://download.osgeo.org/gdal/2.3.2/gdal-2.3.2.tar.gz && \ tar -zvxf gdal-2.3.2.tar.gz && \ cd gdal-2.3.2 && \ # 配置支持扩展 ./configure –with-pg –with-freexl –with-expat && \ make -j 4 && \ make installCMD [ “ogr2ogr”,"–formats" ] ...

January 21, 2019 · 1 min · jiezi

让 TiDB 访问多种数据源 | TiDB Hackathon 优秀项目分享

本文作者是来自 CC 组的兰海同学,他们的项目《让 TiDB 访问多种数据源》在本届 TiDB Hackathon 2018 中获得了二等奖。该项目可以让 TiDB 支持多种外部数据源的访问,针对不同数据源的特点会不同的下推工作,使 TiDB 成为一个更加通用的数据库查询优化和计算平台。我们队伍是由武汉大学在校学生组成。我们选择的课题是让 TiDB 接入若干外部的数据源,使得 TiDB 称为一个更加通用的查询优化和计算平台。为什么选这个课题刚开始我们选择课题是 TiDB 执行计划的实时动态可视化。但是填了报名单后,TiDB Robot 回复我们说做可视化的人太多了。我们担心和别人太多冲突,所以咨询了导师的意见,改成了 TiDB 外部数据源访问。这期间也阅读了 F1 Query 和 Calcite 论文,看了东旭哥(PingCAP CTO)在 PingCAP 内部的论文阅读的分享视频。感觉写一个简单 Demo,还是可行的。系统架构和效果展示如上图所示,TiDB 通过 RPC 接入多个不同的数据源。TiDB 发送利用 RPC 发送请求给远端数据源,远端数据源收到请求后,进行查询处理,返回结果。TiDB 拿到返回结果进一步的进行计算处理。我们通过定义一张系统表 foreign_register(table_name,source_type,rpc_info) 记录一个表上的数据具体来自哪种数据源类型,以及对应的 RPC 连接信息。对于来自 TiKV 的我们不用在这个表中写入,默认的数据就是来自 TiKV。我们想访问一张 PostgreSQL(后面简称为 PG)上的表:首先,我们在 TiDB 上定义一个表(记为表 a),然后利用我们 register_foreign(a,postgresql,ip#port#table_name) 注册相关信息。之后我们就可以通过 select * from a 来读取在 PG 上名为 table_name 的表。我们在设计各个数据源上数据访问时,充分考虑各个数据源自身的特点。将合适的操作下推到具体的数据源来做。例如,PG 本身就是一个完整的数据库系统,我们支持投影、条件、连接下推给 PG 来做。Redis 是一个内存键值数据库,我们考虑到其 Get 以及用正则来匹配键值很快,我们将在 Key 值列的点查询以及模糊匹配查询都推给了 Redis 来做,其他条件查询我们就没有进行下推。具体的运行效果如下:如图所示,我们在远程开了 3 个 RPC Server,负责接收 TiDB 执行过程中的外部表请求,并在内部的系统表中进行了注册三张表,并在 TiDB 本地进行了模式的创建——分别是remotecsv,remoteredis,remotepg,还有一张本地 KV Store 上的 localkv 表。我们对 4 张表进行 Join 操作,效果如图所示,说明如下。1. 远程 csv 文件我们不做选择下推,所以可以发现 csv 上的条件还是在 root(即本地)上做。2. 远程的 PG 表,我们会进行选择下推,所以可以发现 PG 表的 selection 被推到了 PG 上。3. 远程的 Redis 表,我们也会进行选择下推,同时还可以包括模型查询条件(Like)的下推。P.S. 此外,对于 PostgreSQL 源上两个表的 Join 操作,我们也做了Join 的下推,Join 节点也被推送到了 PostgreSQL 来做,具体的图示如下:如何做的由于项目偏硬核的,需要充分理解 TiDB 的优化器,执行器等代码细节。所以在比赛前期,我们花了两三天去研读 TiDB 的优化器,执行器代码,弄清楚一个简单的 Select 语句扔进 TiDB 是如何进行逻辑优化,物理优化,以及生成执行器。之前我们对 TiDB 这些细节都不了解,硬着去啃。发现 TiDB 生成完执行器,会调用一个 Open 函数,这个函数还是一个递归调用,最终到 TableReader 才发出数据读取请求,并且已经开始拿返回结果。这个和以前分析的数据库系统还有些不同。前期为了检验我们自己对 TiDB 的执行流程理解的是否清楚,我们尝试这去让 TiDB 读取本地 csv 文件。比赛正式开始,我们一方面完善 csv,不让其进行条件下推,因为我们远端 RPC 没有处理条件的能力,我们修改了逻辑计划的条件下推规则,遇到数据源是 csv 的,我们拒绝条件下推。另一方面,首先得啃下硬骨头 PostgreSQL。我们考虑了两种方案,第一种是拿到 TiDB 的物理计划后,我们将其转换为 SQL,然后发给 PG;第二种方案我们直接将 TiDB 的物理计划序列化为 PG 的物理计划,发给 PG。我们考虑到第二种方案需要给 PG 本身加接受物理计划的钩子,就果断放弃。可能两天都费在该 PG 代码上了。我们首先实现了 select * from pgtable。主要修改了增加 pgSelectResult 结构体实现对应的结构体。通过看该结构体以及其对应接口函数,大家就知道如何去读取一个数据源上的数据,以及是如何做投影下推。修改 Datasource 数据结构增加对数据源类型,RPC 信息,以及条件字符串,在部分物理计划内,我们也增加相关信息。同时根据数据源信息,在 (e*TableReaderExecutor)buildResp 增加对来源是 PG 的表处理。接着我们开始尝试条件下推:select * from pgtable where … 将 where 推下去。我们发现第一问题:由于我们的注册表里面没有记录外部源数据表的模式信息导致,下推去构建 SQL 的时候根本拿不到外部数据源 PG 上正确的属性名。所以我们暂时保证 TiDB 创建的表模式与 PG 创建的表模式完全一样来解决这个问题。条件下推,我们对条件的转换为字符串在函数 ExpressionToString 中,看该函数调用即可明白是如何转换的。当前我们支持等于、大于、小于三种操作符的下推。很快就到了 1 号下午了,我们主要工作就是进行 Join下推 的工作。Join 下推主要是当我们发现两个 Join 的表都来来自于同一个 PG 实例时,我们就将该 Join 下推给 PG。我们增加一种 Join 执行器:PushDownJoinExec。弄完 Join 已经是晚上了。而且中间还遇到几个 Bug,首先,PG 等数据源没有一条结果满足时的边界条件没有进行检查,其次是,在 Join 下推时,某些情况下 Join 条件未必都是在 On 子句,这个时候需要考虑 Where 子句的信息。最后一个,如果使得连接和条件同时下推没有问题。因为不同表的相同属性需要进行区分。主要难点就是对各个物理计划的结构体中的解析工作。到了晚上,我们准备开始着手接入 Redis。考虑到 Redis 本身是 KV 型,对于给定 Key 的 Get 以及给定 Key 模式的匹配是很快。我们直接想到对于 Redis,我们允许 Key 值列上的条件下推,让 Redis 来做过滤。因为 Redis 是 API 形式,我们单独定义一个简单请求协议,来区别单值,模糊,以及全库查询三种基本情况,见 RequestRedis 定义。Redis 整体也像是 PG 一样的处理,主要没有 Join 下推这一个比较复杂的点。我们之后又对 Explain 部分进行修改,使得能够打印能够反映我们现在加入外部数据源后算子真实的执行情况,可以见 explainPlanInRowFormat 部分代码。之后我们开始进行测试每个数据源上的,以及多个数据源融合起来进行测试。不足之处1. 我们很多物理计划都是复用 TiDB 本身的,给物理计划加上很多附属属性。其实最好是将这些物理计划单独抽取出来形成一个,不去复用。2. Cost 没有进行细致考虑,例如对于 Join 下推,其实两张 100 万的表进行 Join 可能使得结果成为 1000 万,那么网络传输的代价反而更大了。这些具体算子下推的代价还需要细致的考虑。比较痛苦的经历1. TiDB 不支持 Create Funtion,我们就只好写内置函数,就把另外一个 Parser 模块拖下来,自己修改加上语法,然后在加上自己设计的内置函数。2. 最痛苦还是两个方面,首先 Golang 语言,我们之前没有用得很多,经常遇到些小问题,例如 interface 的灵活使用等。其次就是涉及的 TiDB 的源码模块很多,从优化器、执行器、内置函数以及各种各样的结构。虽然思路很简单,但是改动的地方都很细节。收获比赛过程中,看到了非常多优秀选手,以及他们酷炫的作业,感觉还是有很长的路要走。Hackathon 的选手都好厉害,听到大家噼里啪啦敲键盘的声音,似乎自己也不觉得有多累了。人啊,逼一下自己,会感受到自己无穷的力量。通过这次活动,我们最终能够灵活使用 Golang 语言,对 TiDB 整体也有了更深入的认识,希望自己以后能够称为 TiDB 的代码贡献者。 最后非常感谢 PingCAP 这次组织的 Hackathon 活动,感谢导师团、志愿者,以及还有特别感谢导师张建的指导。TiDB Hackathon 2018 共评选出六个优秀项目,本系列文章将由这六个项目成员主笔,分享他们的参赛经验和成果。我们非常希望本届 Hackathon 诞生的优秀项目能够在社区中延续下去,感兴趣的小伙伴们可以加入进来哦。 ...

December 14, 2018 · 2 min · jiezi

Wire Protocol of PostgreSQL Queries in a Nutshell

I was working on a pull request to improve the performance of executemany() in asyncpg, who talks to the PostgreSQL server directly in its wire protocol (comparing to psycopg2 who uses libpq to speak the wire language for itself). Though the documentation for the protocol explained mostly everything, I found it a bit boring to read and it’s easy to miss some very important details if you don’t read every word. So I shall try to explain the message flow again here, hopefully in a nutshell.I’ve also wrote some PoC code in Python for this post, and the source of the diagrams can be found here. please feel free to download and play with it.The StartMost PostgreSQL clients exchange data with the server through a single streaming connection - a TCP connection or UNIX domain socket connection for example. Each connection keeps exactly one Session on the server side. Sessions are maintained by separate processes, so they are isolated from each other, like this:When the connection is established, the client must authenticate itself to the server, and tell the server which database to use for this Session, by sending some Messages defined in the protocol back and forth. Once the authentication process is done successfully, the server always send a ReadyForQuery Message to the client indicating that it’s good to move forward.In practice, the actual start-up message flow may be more complex than this. I’m skipping the details here and jumping to the query message flow.Simple QueryClient may initiate two types of queries: the Simple Query or the Extended Query. We’ll start with the simple one. It is actually as simple as this:As you can see, Simple Query starts with the client sending a Query Message with the actual SQL command. Once received, the server will process the SQL and execute it, and return the result status string back to the client in a CommandComplete Message. Likewise, the server will send a ReadyForQuery Message at the end, telling the client that it is ready for more queries.Pipelining, Batching and TransactionsHowever, it is unnecessary for the client to wait for ReadyForQuery to send the next query - server sends it only to indicate that the job for the query is done, there won’t be further responses returned for that query. The server can handle all the queries coming from the stream like a pipeline worker, returning the responses in the same order. So as far as the client could recognize who is who, it is actually okay to do this:Simple Query also allows one Query Message with multiple SQL commands separated with semicolons (;). So here is a similar way to insert 3 rows with a single Query Message:Much less ReadyForQuery noises, nice! However, this approach is actually different than the previous one. The server shall execute all SQL commands from the same Query Message in an implicit transaction, unless there is an explicit transaction in current Session. In this case, failure from any of the three SQL commands will rollback the implicit transaction, thus none of the commands could insert anything. For example:Here the second INSERT … VALUES (8) fails with a unique constraint check error, then the implicit transaction gets rolled back, skipping the third INSERT … VALUES (9) at all.Instead in previous example with three Query Messages, each SQL command lives in their own transaction, so one failing command couldn’t stop another from inserting successfully. In order to achieve the same transactional effect, we need to create an explicit transaction with the BEGIN…END SQL commands:As you might have noticed, the ReadyForQuery Messages now provide different values: INTRANS means the Session has an active transaction when the server sends the Message, INERROR means the Session is in a failed transaction (indicating that further queries like INSERT … 11 will be rejected until the transaction is closed), and IDLE means the Session is not in a transaction block any more.You might also have noticed that, this example had two ErrorResponses, but previous example had only one. This is because ReadyForQuery cleared the “error returned, skipping all messages” state on the server side. For example, if we combine the INSERT … 11 into previous Message like this: Query(“INSERT … VALUES (10); INSERT … VALUES (11)”), then we’ll have one ErrorResponse again. We’ll get to this again later.Row SetsNow let’s take a look at the SQL that actually returns data, e.g. a SELECT command:In this diagram, there are two more types of Messages before the usual CommandComplete:RowDescription contains all information of each column of the result, including column name, column type and more.DataRow is simply one data row of the result, including all values of each column in the same order as described in the RowDescription Message.Obviously DataRow Message may repeat as many times as needed. Also, there can be no DataRow Message at all, indicating an empty result with “table header” (RowDescription) only.Different types of SQL commands may also output other types of responses like CopyInResponse, CopyOutResponse or NoticeResponse, but I’m not covering them here.Behind the ScenesOn the backend, the PostgreSQL server is actually doing more to generate such responses. The following diagram describes roughly how this process looks like:On receiving a Query Message, the server will firstly start an implicit transaction if there is no transaction in the Session.parse - PostgreSQL server will then parse the given SQL string into a prepared statement in the Session. And yes it is the same kind of prepared statement as you can generate with SQL PREPARE, only that this one here has no name. Thus it is also called unnamed prepared statement, or unnamed statement in short.bind - Then the server will create a portal in current transaction with above prepared statement, and run the query planning. Likewise, portal is also known as server-side cursor, which you can create with SQL DECLARE CURSOR. Similarly the portal in Simple Query is an unnamed portal.With a portal, the server has enough knowledge about the result, so it will send over a RowDescription Message.execute - Eventually, the server executes the portal, and result rows get generated and sent to the client. When the cursor hits the end, a CommandComplete Message is sent.sync - At last, the server closes the implicit transaction - that means either to commit if all good, or rollback on error. However, it will not close an explicit transaction, because in that case Query(“BEGIN”) won’t work. Finally, a ReadyForQuery Message is sent to the client after all this.If there are multiple SQL commands in one Query Message, above process is simply repeated several times, but sync runs only once at the very end so that all SQL commands share the same implicit transaction.Extended QueryFor a PostgreSQL server, Extended Query runs in the same way as above - only that it breaks down each step into separate Messages, allowing fine control to gain much more possibilities. For the same example with Extended Query:In brief, we parsed the SQL string into stmt1, bound it into portal1, described the portal for RowDescription, executed the portal for DataRows, then put an end with Sync. The difference is, the prepared statement and portal now have names. It is possible to create multiple prepared statements or portals and use them alternatively.PipeliningActually in previous diagram, the client wasn’t waiting for any responses to send the next Message. Because the responses won’t arrive at all until Sync is issued (if everything goes well). We put it that way to better explain the consequences of each Message. In fact the network sequence is more like this:It is okay for the client to send each Message one by one, or concatenate them into a big buffer and send altogether. Because the server will do the same buffering thing to save round-trip time, and only flush the buffer into the wire when Sync or Flush is issued, or as soon as an error occurred.Comparing to Sync generates ReadyForQuery, Flush generates nothing at all but only flushes the server-side buffer.TransactionBecause Extended Query is simply Simple Query extended, some similar rules we discussed previously also apply here. Take implicit transaction for example: within a Session when the PostgreSQL server receives a Message (one of Parse, Bind, Execute or Describe) from the client, it will firstly check current transaction state. If there was no transaction (either explicit or implicit - in IDLE state), it will start an implicit one immediately before handling the Message.Handling Messages may cause errors. In implicit transactions, errors lead to rollbacks; but in explicit transactions, they put the Session into INERROR state:In addition for extended query, you may issue as many Messages as you want before Sync - you can Parse 5 different SQLs, Bind 3 of them, and Execute them all. But a failing Message will set the Session into ignore_till_sync mode, meaning that the server will ignore any Message until Sync is found. This is similar to using one Simple Query Message to execute many SQLs joint with semicolons (;), one failing SQL cause the rest ignored. At last, errors always cause an immediate flush of the server-side buffer.If the Message turns out to be a Sync, it shall clear the ignore_till_sync mode first. Then the server will check if the current transaction is an implicit one. If yes, it will try to commit the transaction. Sync won’t touch an explicit transaction, but it will send a ReadyForQuery response and flush the server-side buffer anyhow:Therefore, Sync is the normal way closing an implicit transaction - it would commit a good transaction, or reset an aborted transaction to normal:You may also issue an explicit COMMIT or ROLLBACK SQL command to end an implicit transaction in the way you want. But 1), the PostgreSQL server shall complain about it with an extra NoticeResponse warning, and 2), in ignore_till_sync mode, the server will ignore any Messages other than Sync, even if it is a ROLLBACK. Therefore, it is only meaningful to rollback an implicit transaction with an explicit ROLLBACK while there was no error:Behind the scene, the PostgreSQL server is using a much more complex state machine to maintain the transaction block state. This diagram only shows an essential part of it:Note that the purple tags are actual transaction boundaries. The transaction state we get from ReadyForQuery Message are simply judged by the colors of each state. Please note that, if you get a ReadyForQuery from an implicit transaction (the two states in dashed frame), it always states that the transaction is IDLE because Sync does the commit first. I guess that’s why the STARTED state is actually categorized as an IDLE state in PostgreSQL source code, but I’m marking it as INTRANS anyway here because the transaction did start beforehand. It is also interesting to see that, any transaction starts as an implicit one - only BEGIN commands (or its varient) could mark it as an explicit transaction.In explicit transactions, Extended Query may also trigger the ignore_till_sync mode with a failing Message. As Sync won’t rollback the explicit transaction, it is only used to clear the ignore_till_sync mode, making space for ROLLBACK command. Therefore, it is rare to execute multiple SQL commands within one Sync. The usual pattern is Bind -> Execute -> Sync, with optional Parse and Describe. Externally, the state transitioning looks like this:If an operation is not seen for a state in this diagram, it means this missing operation won’t lead to a state change. For example, issuing a Sync in explicit INTRANS has no effect but flushing the buffer. And success means any other Message that runs successfully (e.g. executing SELECT now()), while error means it results with an error (e.g. executing SELECT 1/0).Additionally, please be aware that, using Query is identical to call Parse -> Bind -> Describe -> Execute -> Sync. If you are mixing Simple Query in an Extended Query, the Query will close the implicit transaction in Extended Query.ParameterYou may wonder why having the portal trouble at all when there is already prepared statement - why didn’t PostgreSQL merge the cursor feature into prepared statements? The reason is about caching prepared statements. It is a waste to repeatingly parse the same SQL over and over again: say for a web server we need to load user data for every request, we may use SELECT * FROM users WHERE id = 235 for user 235, and SELECT * FROM users WHERE id = 169 for user 169. The only difference in SQL is the user’s ID - if we can turn that into a parameter, we can then parse the SQL string only once and reuse the prepared statement for different users.This is exactly how portal helps: it allows binding the actual parameter values with the same prepared statements into different portals. For example:The parameter placeholder is $1, indicating the first parameter in the list provided in Bind. Each portal is an actual execution handle of the query with specific parameter values. You can have as many portals as you need, as far as the stmt5 lives.LifetimeNamed prepared statements live until the end of the Session, unless explicitly freed with the Close(“S”, stmt1") Message (“S” for Statement). That means if not closed, you may use stmt1 whenever you want within the same TCP connection. But before closing, you cannot create another prepared statement with the same again in the same Session, doing so will end up with an ErrorResponse.Prepared statements are usually managed by PostgreSQL drivers like asyncpg in a way of LRU cache, in order to save resources parsing the same SQL strings.However, named portals cannot live that long - they lasts until the end of the transaction if not explicitly closed with Close(“P”, “portal1”) Message (“P” for Portal). In previous example, there was only one implicit transaction that ended at Sync(), so it is possible to reuse the names portal1 and portal2 after that.It is possible to manually create or close unnamed prepared statements and portals in Extended Query - just setting the name to an empty string ("") will do. They are identical to named statements and portals except for one thing: it is not an error to create a new unnamed statement or portal if an existing one wasn’t closed - it’s simply overwritten. This is extremely convenient if you need some one-time use statements or portals - just create one and use it at once, then forget about it. But be aware that, Simple Query also creates unnamed statements and portals, mixing using it will cause unnamed statements or portals you created overwritten.Server-side CursorIf not closed, portals may live throughout a transaction. It is designed this way so that it can yield results incrementally like a cursor. Note the second parameter 0 in Execute Messages previously - it meant to fetch all results. If given a positive number, it will fetch at most that many rows from the result set. For other SQL commands that doesn’t return results, this parameter has no effect - the command is always executed to completion.If the limit is reached before the end of the result, a PortalSuspended Message will be returned, like the first Execute in this diagram. But, receiving a PortalSuspended doesn’t necessarily mean there are more rows to receive - the second fetch may also get an empty list if the limit number of the first fetch is exactly the same as the row count. It is also worth noting that, the final row count in CommandComplete Message reflects only the number of rows in the last fetch, not the total number of all the rows returned.There is no MOVE equivalent in Extended Query to move the cursor without returning. Instead you may directly use the SQL command, using the portal name as cursor name.DescribeThe Describe Message can be used on either prepared statements or portals, in order to get information of them. This selection is specified by the first parameter, where P means portal, and S means statement.Describing a portal generates a RowDescription response like the one we got in Simple Query. It is usually essential for processing following DataRows if any. It returns NoData if describing a portal that returns nothing like an UPDATE command without RETURNING.Describing a statement is a bit complicated - it returns two Messages. The first is ParameterDescription which describes the parameters and their types in the given statement. The second is still a RowDescription (or NoData), but it may lack some typing information because the statement is not bound to specific parameters thus some types of variables are still unknown.The EndThere are still a lot more I didn’t cover here like COPY, NOTIFY, TLS and more. But it’s already been days to write those above and I’m already getting messy with part of it, so I’ll end this with two more closing topics.Cancel a Running QueryPostgreSQL allows canceling a running query from outside, by establishing a new connection to the server and send over a CancelRequest Message instead of the normal StartupMessage:The Canceller may or may not be a a part of Client, as far as the CancelRequest contains essential subprocess ID and secret key of the target Session, which the Client could obtain during its initial authentication. Because the signal may arrive at any time, the cancellation is not a consistent event. That is to say, after sending the CancelRequest, the Client should be ready to face any possible responses including successful results or errors.ByeFor a graceful shutdown, it’s usually the Client sending a Terminate Message and close the connection. On receiving Terminate, the server will also close the connection and terminate the Session, rolling back any pending transactions. It is worth noting that, even though a broken connection without Terminate may do the same, the server would firstly finish any query at hand before noticing the disconnection, therefore separate SQL commands without transaction may still succeed during ungraceful shutdown.Referenceshttps://www.pgcon.org/2014/sc…https://www.postgresql.org/do...https://www.postgresql.org/do… ...

November 25, 2018 · 14 min · jiezi

PostgreSQL的实践一:初识

简介和认知发音post-gres-q-l服务(server)一个操作系统中可以启动多个postgres服务。每个服务由多个进程组成,为首的进程名为postmaster。每个服务要占用一个端口,多个服务不能共享端口。每个服务都有一个data目录用于存放数据,目录不允许修改,否则会破坏数据库,并且无法修复。服务使用4字节长的内部事务标识符,即时发生重叠后仍然继续使用,这会导致问题,所以需要定期进行VACUUM操作。数据库(database)一个服务中可以拥有多个数据库。数据库默认是任何用户可连接的,创建好后需要修改相应的权限。数据库之间的数据是隔离的,不能进行联表。数据库默认的数据块大小为8192。模式(schema)一个数据库中可以有多个模式,模式相当于表的命名空间,类似于mysql中的database,可以使用带模式的完整名称来访问或者创建对象。不同模式之间的表是可以联表查询的。可以通过对用户设置search_path参数来指定默认搜索的模式。表(table)一个模式中可以有多张表。表是由多个关系元素组成的,大字段数据放在另一个名为TOAST的表中,每张表都有一个TOAST表和TOAST索引。用双引号括起来的表和没用双引号括起来的表是不一样的,即使名字一样。双引号括起来的表区分大小写,没用双引号括起来的表不区分大小写。列(column)每张表都由许多列组成,每一列有一个列名、类型、默认值等属性,用来存储每一条记录中的各种值。文本类型统一由一种数据类型存储,支持长度从1B到1G,经过优化,存储少的时候很高效,存储多的时候会自动管理和压缩。自增类型serial本质上就是整数,通过创建并关联到一个SEQUENCE类型的对象来记录自增值。表空间(tablespace)默认情况下,所有的数据都会放在postgres指定的data目录下,通过定义表空间,可以让postgres将数据存放在不同的设备上。表空间是通过软链接来实现的。建议为每个数据库设立一个单独的表空间,尤其是不同数据库中有同名的模式或者表的时候。postgres=# CREATE TABLESPACE tbs LOCATION ‘/usr/local/tbs’;视图(view)视图本质上是预定义好的一个sql查询,以一张表的形式给出,在每次调用时都会执行相应的sql查询。postgres=# CREATE VIEW view AS SELECT * FROM tb;当视图足够简单的时候,postgres是支持视图更新的,相应的更新会传递到相应的表中。还可以使用INSTEAD OF触发器或者规则来实现视图更新,请参考具体的操作手册。物化视图可以预先将数据查询出来,这样调用的时候就不必反复查询了,更新需要手动更新。postgres=# CREATE MATERIALIZED VIEW view AS SELECT * FROM tb;postgres=# REFRESH MATERIALIZED VIEW view;行(row)行即表中的一条数据。postgres中每个行都有一个行版本,而且还有两个系统列xmin和xmax,分别标示这个行被创建和删除的事务。删除时,设置xmax为删除事务号,不会实际执行删除。UPDATE操作被认为是紧跟INSERT操作后的DELETE操作。索引(index)索引可以用来给表添加约束或者提高查询速度。在涉及高比例插入删除的表中,会造成索引膨胀,这时候可以重建索引。reindexdb创建CONCURRENTLY索引时不会持有全表锁,这条指令分成两个步骤,第一部分创建索引并标记为不可用,这时候INSERT、UPDATE、DELETE操作已经开始维护索引了,但是查询不能使用索引。建立完毕后才会被标记为可用。postgres=# CREATE CONCURRENTLY INDEX index ON tb(id);可以手工设置索引的可用性。UPDATE pg_index SET indisvalid = false WHERE indexrelid = index::regclass;pgsql 中表空间/数据库/模式 的关系表空间是物理结构,同一表空间下可以有多个数据库数据库是逻辑结构,是表/索引/视图/存储过程的集合,一个数据库下可以有多个schema模式是逻辑结构,是对数据库的逻辑划分安装# vist https://www.postgresql.org/download/# Interactive installer by EnterpriseDB -> 选择10.5版本的Windows x86-64下载1. 一路的next安装,当然你可以自己选择安装的目录2. 提示输入postgres帐号的密码,你可以根据自己的喜好,设置一个,比如这里我设置了:1234562. 提示安装插件扩展,取消即可,暂时不需要安装psql客户端简单实用连接# $MY_POSTGRES_PATH = D:\PostgreSQL; 这个环境参数代表我安装的Postgresql服务器所在的目录# $MY_POSTGRES_PATH/bin/psql -U postgres$MY_POSTGRES_PATH/bin/scripts/runpsql# 依次默认回车,如果有需要调整参数,你可以自定义# 输入123456#outputServer [localhost]:Database [postgres]:Port [5432]:Username [postgres]:用户 postgres 的口令:psql (10.5)输入 “help” 来获取帮助信息.postgres=## 输入help得到以下提示postgres=# help您正在使用psql, 这是一种用于访问PostgreSQL的命令行界面键入: \copyright 显示发行条款 \h 显示 SQL 命令的说明 ? 显示 pgsql 命令的说明 \g 或者以分号(;)结尾以执行查询 \q 退出postgres=## \l 查看已存在的数据库postgres-# \l 数据库列表 名称 | 拥有者 | 字元编码 | 校对规则 | Ctype | 存取权限———–+———-+———-+—————————————————–+—————————————————–+———————– postgres | postgres | UTF8 | Chinese (Simplified)_People’s Republic of China.936 | Chinese (Simplified)_People’s Republic of China.936 | template0 | postgres | UTF8 | Chinese (Simplified)_People’s Republic of China.936 | Chinese (Simplified)_People’s Republic of China.936 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | Chinese (Simplified)_People’s Republic of China.936 | Chinese (Simplified)_People’s Republic of China.936 | =c/postgres + | | | | | postgres=CTc/postgres(3 行记录)# 我们可以发现默认存在postgres、template0和template1数据库,templateX是模板数据库# template1为可修改模版库,template0为不可修改模版库创建数据库postgres=# create database testdb;# CREATE DATABASE# \c = \connectpostgres=# \c testdb;# 您现在已经连接到数据库 “testdb”,用户 “postgres”.创建表# 查看表testdb=# \d# Did not find any relations.# 创建表testdb=# create table test1(id int primary key, name varchar(50));# CREATE TABLEtestdb=# \d 关联列表 架构模式 | 名称 | 类型 | 拥有者———-+——-+——–+———- public | test1 | 数据表 | postgres(1 行记录)# 架构模式(schema)我们后续会讲,暂时你可以先理解为一个数据库逻辑分类的概念,默认创建数据库都会有一个public的schema常规显示设置# 设置显示查询时间\timing on# 设置border的边框内外都有\pset border 2# 查看编码\encoding# 设置编码\encoding UTF8# 开启扩展显示,纵向打印每列数据\x# 例子:testdb=# select * from test1;+-[ RECORD 1 ]-+| id | 1 || name | qkl |+——+—–+# 设置命令执行的真正sql:on打开 off关闭\set ECHO_HIDDEN on\set ECHO_HIDDEN off# 案例:testdb=# \set ECHO_HIDDEN ontestdb=# \d********* 查询 *********SELECT n.nspname as “Schema”, c.relname as “Name”, CASE c.relkind WHEN ‘r’ THEN ’table’ WHEN ‘v’ THEN ‘view’ WHEN ’m’ THEN ‘materialized view’ WHEN ‘i’ THEN ‘index’ WHEN ‘S’ THEN ‘sequence’ WHEN ’s’ THEN ‘special’ WHEN ‘f’ THEN ‘foreign table’ WHEN ‘p’ THEN ’table’ END as “Type”, pg_catalog.pg_get_userbyid(c.relowner) as “Owner"FROM pg_catalog.pg_class c LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespaceWHERE c.relkind IN (‘r’,‘p’,‘v’,’m’,‘S’,‘f’,’’) AND n.nspname <> ‘pg_catalog’ AND n.nspname <> ‘information_schema’ AND n.nspname !~ ‘^pg_toast’ AND pg_catalog.pg_table_is_visible(c.oid)ORDER BY 1,2;**************************关联列表+-[ RECORD 1 ]——–+| 架构模式 | public || 名称 | test1 || 类型 | 数据表 || 拥有者 | postgres |+———-+———-+常用命令testdb-# ?一般性 \copyright 显示PostgreSQL的使用和发行许可条款 \crosstabview [COLUMNS] 执行查询并且以交叉表显示结果 \errverbose 以最冗长的形式显示最近的错误消息 \g [文件] or; 执行查询 (并把结果写入文件或 |管道) \gexec 执行策略,然后执行其结果中的每个值 \gset [PREFIX] 执行查询并把结果存到psql变量中 \gx [FILE] as \g, but forces expanded output mode \q 退出 psql \watch [SEC] 每隔SEC秒执行一次查询帮助 ? [commands] 显示反斜线命令的帮助 ? options 显示 psql 命令行选项的帮助 ? variables 显示特殊变量的帮助 \h [名称] SQL命令语法上的说明,用显示全部命令的语法说明查询缓存区 \e [FILE] [LINE] 使用外部编辑器编辑查询缓存区(或文件) \ef [FUNCNAME [LINE]] 使用外部编辑器编辑函数定义 \ev [VIEWNAME [LINE]] 用外部编辑器编辑视图定义 \p 显示查询缓存区的内容 \r 重置(清除)查询缓存区 \w 文件 将查询缓存区的内容写入文件输入/输出 \copy … 执行 SQL COPY,将数据流发送到客户端主机 \echo [字符串] 将字符串写到标准输出 \i 文件 从文件中执行命令 \ir FILE 与 \i类似, 但是相对于当前脚本的位置 \o [文件] 将全部查询结果写入文件或 |管道 \qecho [字符串] 将字符串写到查询输出串流(参考 \o)Conditional \if EXPR begin conditional block \elif EXPR alternative within current conditional block \else final alternative within current conditional block \endif end conditional block资讯性 (选项: S = 显示系统对象, + = 其余的详细信息) \d[S+] 列出表,视图和序列 \d[S+] 名称 描述表,视图,序列,或索引 \da[S] [模式] 列出聚合函数 \dA[+] [PATTERN] list access methods \db[+] [模式] 列出表空间 \dc[S+] [PATTERN] 列表转换 \dC[+] [PATTERN] 列出类型强制转换 \dd[S] [PATTERN] 显示没有在别处显示的对象描述 \dD[S+] [PATTERN] 列出共同值域 \ddp [模式] 列出默认权限 \dE[S+] [PATTERN] 列出引用表 \det[+] [PATTERN] 列出引用表 \des[+] [模式] 列出外部服务器 \deu[+] [模式] 列出用户映射 \dew[+] [模式] 列出外部数据封装器 \df[antw][S+] [模式] 列出[只包括 聚合/常规/触发器/窗口]函数 \dF[+] [模式] 列出文本搜索配置 \dFd[+] [模式] 列出文本搜索字典 \dFp[+] [模式] 列出文本搜索解析器 \dFt[+] [模式] 列出文本搜索模版 \dg[S+] [PATTERN] 列出角色 \di[S+] [模式] 列出索引 \dl 列出大对象, 功能与\lo_list相同 \dL[S+] [PATTERN] 列出所有过程语言 \dm[S+] [PATTERN] 列出所有物化视图 \dn[S+] [PATTERN] 列出所有模式 \do[S] [模式] 列出运算符 \dO[S+] [PATTERN] 列出所有校对规则 \dp [模式] 列出表,视图和序列的访问权限 \drds [模式1 [模式2]] 列出每个数据库的角色设置 \dRp[+] [PATTERN] list replication publications \dRs[+] [PATTERN] list replication subscriptions \ds[S+] [模式] 列出序列 \dt[S+] [模式] 列出表 \dT[S+] [模式] 列出数据类型 \du[S+] [PATTERN] 列出角色 \dv[S+] [模式] 列出视图 \dx[+] [PATTERN] 列出扩展 \dy [PATTERN] 列出所有事件触发器 \l[+] [PATTERN] 列出所有数据库 \sf[+] FUNCNAME 显示一个函数的定义 \sv[+] VIEWNAME 显示一个视图的定义 \z [模式] 和\dp的功能相同格式化 \a 在非对齐模式和对齐模式之间切换 \C [字符串] 设置表的标题,或如果没有的标题就取消 \f [字符串] 显示或设定非对齐模式查询输出的字段分隔符 \H 切换HTML输出模式 (目前是 关闭) \pset [NAME [VALUE]] set table output option (NAME := {border|columns|expanded|fieldsep|fieldsep_zero| footer|format|linestyle|null|numericlocale|pager| pager_min_lines|recordsep|recordsep_zero|tableattr|title| tuples_only|unicode_border_linestyle| unicode_column_linestyle|unicode_header_linestyle}) \t [开|关] 只显示记录 (目前是 关闭) \T [字符串] 设置HTML <表格>标签属性, 或者如果没有的话取消设置 \x [on|off|auto] 切换扩展输出模式(目前是 关闭)连接 \c[onnect] {[DBNAME|- USER|- HOST|- PORT|-] | conninfo} 连接到新数据库(当前是"testdb”) \conninfo 显示当前连接的相关信息 \encoding [编码名称] 显示或设定客户端编码 \password [USERNAME] 安全地为用户更改口令操作系统 \cd [目录] 更改目前的工作目录 \setenv NAME [VALUE] 设置或清空环境变量 \timing [开|关] 切换命令计时开关 (目前是 开启) ! [命令] 在 shell中执行命令或启动一个交互式shell变量 \prompt [文本] 名称 提示用户设定内部变量 \set [名称 [值数]] 设定内部变量,若无参数则列出全部变量 \unset 名称 清空(删除)内部变量大对象 \lo_export LOBOID 文件 \lo_import 文件 [注释] \lo_list \lo_unlink LOBOID 大对象运算 ...

November 5, 2018 · 4 min · jiezi