Quantcast
Channel: Archives des PostgreSQL - dbi Blog
Viewing all 528 articles
Browse latest View live

Maintenance scenarios with EDB Failover Manager (1) – Standby node

$
0
0

Recently at a customer we again implemented a PostgreSQL architecture as described some time ago. When we delivered the first draft of the documentation the question popped up how to handle maintenance tasks in a failover cluster protected by EDB Failover Manager. So, here we go…

The setup of my little test environment is as follows:

IP Description
192.168.22.243 Current PostgreSQL hot standby instance
192.168.22.245 Currernt PostgreSQL primary instance
192.168.22.244 EDB Failover Manager Witness Node + EDB BART
192.168.22.250 Virtual IP that is used for client connections to the master database

In words there is one master database streaming to a hot standby database. On the third node there is EDB BART for backup and recovery and EDB Failover Manager as a witness. For this specific setup we used a VIP that will fail over as well if the master database goes done for any reason.

Using the EFM command line utility the current status of the cluster can be displayed:

postgres@edbbart:/home/postgres/ [pg950] efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Standby     192.168.22.243       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.245 192.168.22.243

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/320001E8       
	Standby     192.168.22.243       0/320001E8       

	Standby database(s) in sync with master. It is safe to promote.

This clearly shows the cluster is healthy at the moment and a promote could be safely executed. Note that automatic failover is disabled here.

What do you need to do when you want to perform maintenance on the current standby node and you need to take the database down for being able to do so? Actually not much. Lets confirm that this is really the standby node:

postgres@edbppas:/home/postgres/ [PGSITE1] psql postgres
psql.bin (9.5.0.5)
Type "help" for help.

postgres=# select * from pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 t
(1 row)

postgres=# 

Fine. I’ll be doing it the hard way and will just reboot the server (autostart for the PostgreSQL instance is disabled in my case):

[root@edbppas ~] reboot
Connection to 192.168.22.243 closed by remote host.
Connection to 192.168.22.243 closed.

What is the status of my cluster now?

postgres@edbbart:/home/postgres/ [pg950] efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.245 192.168.22.243

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/320002C8       

	No standby databases were found.

The standby database disappeared. Once the node comes up again lets check the failover manager on that node:

[root@edbppas ~] systemctl status efm-2.0.service
efm-2.0.service - EnterpriseDB Failover Manager 2.0
   Loaded: loaded (/usr/lib/systemd/system/efm-2.0.service; enabled)
   Active: failed (Result: exit-code) since Fri 2016-04-08 15:51:51 CEST; 1min 39s ago
  Process: 583 ExecStart=/bin/java -cp /usr/efm-2.0/lib/EFM-2.0.4.jar com.enterprisedb.hal.main.ServiceCommand start /etc/efm-2.0/${CLUSTER}.properties (code=exited, status=1/FAILURE)

Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ]
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ] 4/8/16 3:51:50 PM com.enterprisedb.hal.exec.ExecUtil performExe...ey efm]
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ]
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ] 4/8/16 3:51:50 PM com.enterprisedb.hal.exec.ExecUtil performExe...Out=''}
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ]
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ] 4/8/16 3:51:50 PM com.enterprisedb.hal.nodes.HalAgent shutdown ...xiting.
Apr 08 15:51:51 edbppas java[583]: [ 4/8/16 3:51:51 PM ]
Apr 08 15:51:51 edbppas systemd[1]: efm-2.0.service: control process exited, code=exited status=1
Apr 08 15:51:51 edbppas systemd[1]: Failed to start EnterpriseDB Failover Manager 2.0.
Apr 08 15:51:51 edbppas systemd[1]: Unit efm-2.0.service entered failed state.
Hint: Some lines were ellipsized, use -l to show in full.
[root@edbppas ~] cat /var/log/efm-2.0/efm.log
[root@edbppas ~] 

Hm, not so good. Although the service is enabled for automatic restart it did not come up. How to fix it? The database is still configured for recovery:

postgres@edbppas:/home/postgres/ [PGSITE1] cat $PGDATA/recovery.conf
standby_mode = 'on'
primary_slot_name = 'standby1'
primary_conninfo = 'user=postgres password=admin123 host=192.168.22.245 port=4445 sslmode=prefer sslcompression=1'
recovery_target_timeline = 'latest'
trigger_file='/u02/pgdata/PGSITE1/trigger_file'

It should be safe to start it up. Once it comes up, looking at the logfile:

2016-04-08 14:25:24.350 GMT - 3 - 2428 -  - @ LOG:  consistent recovery state reached at 0/320001E8
2016-04-08 14:25:24.350 GMT - 4 - 2428 -  - @ LOG:  redo starts at 0/320001E8
2016-04-08 14:25:24.350 GMT - 5 - 2428 -  - @ LOG:  invalid record length at 0/320002C8
2016-04-08 14:25:24.351 GMT - 4 - 2426 -  - @ LOG:  database system is ready to accept read only connections
2016-04-08 14:25:24.359 GMT - 1 - 2432 -  - @ LOG:  started streaming WAL from primary at 0/32000000 on timeline 2

Fine. Streaming started again and from a database perspective we are fine. But what about our failover manager? In this case we need to tell failover manager to rejoin the cluster by adding all noes to the efm.nodes file:

[root@edbppas efm-2.0] pwd
/etc/efm-2.0
[root@edbppas efm-2.0] cat efm.nodes
# List of node address:port combinations separated by whitespace.
192.168.22.244:9998 192.168.22.245:9998 192.168.22.243:9998

Once this is ready we can restart and everything is back to normal operations:

[root@edbppas efm-2.0] systemctl start efm-2.0.service
[root@edbppas efm-2.0] /usr/efm
efm/     efm-2.0/ 
[root@edbppas efm-2.0] /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Witness     192.168.22.244       UP     N/A       
	Standby     192.168.22.243       UP     UP        
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/330000D0       
	Standby     192.168.22.243       0/330000D0       

	Standby database(s) in sync with master. It is safe to promote.

Note 1: If you need to reboot the whole node where currently the standby is running on you’ll need to rejoin to the cluster.

What happens if we stop the standby database without rebooting the node?

postgres@edbppas:/home/postgres/ [PGSITE1] pgstop
waiting for server to shut down.... done
server stopped
postgres@edbppas:/home/postgres/ [PGSITE1] efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        
	Standby     192.168.22.243       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/330000D0       
	Unknown     192.168.22.243       UNKNOWN          Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

	One or more standby databases are not in sync with the master database.

The configuration itself is still fine but the standby database is reported as “UNKNOWN”. This is fine, in this case you can just restart the instance:

postgres@edbppas:/home/postgres/ [PGSITE1] pgstart
server starting
postgres@edbppas:/home/postgres/ [PGSITE1] 2016-04-08 14:35:50.411 GMT - 1 - 3202 -  - @ LOG:  redirecting log output to logging collector process
2016-04-08 14:35:50.411 GMT - 2 - 3202 -  - @ HINT:  Future log output will appear in directory "/u02/pgdata/PGSITE1/pg_log".

postgres@edbppas:/home/postgres/ [PGSITE1] efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Witness     192.168.22.244       UP     N/A       
	Idle        192.168.22.243       UP     UNKNOWN   
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/330000D0       

	No standby databases were found.

Idle Node Status (idle nodes ignored in XLog location comparisons):

	Address              XLog Loc         Info
	--------------------------------------------------------------
	192.168.22.243       0/330000D0       DB is in recovery.

The standby now is reported as “DB is in recovery.” How to fix this? Use the “resume” command:

[root@edbppas ~] /usr/efm-2.0/bin/efm resume efm
Resume command successful on local agent.
[root@edbppas ~] /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Standby     192.168.22.243       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/34000060       
	Standby     192.168.22.243       0/34000060       

	Standby database(s) in sync with master. It is safe to promote.

Ready again.

Note 2: If you take down the standby database: Once you started it up again use the “resume” command to return to normal operation.

 

Cet article Maintenance scenarios with EDB Failover Manager (1) – Standby node est apparu en premier sur Blog dbi services.


The (almost) same sample schema for all major relational databases (1) – PostgreSQL

$
0
0

The are times when it would be nice to have the same sample schema in all relational databases you or your company are working on. This is great if you want to compare how different databases execute the same tasks on the same data. This can be great if you want to test logical replication between different databases and this might be great if you want to test migration tools that support you in migrating from one database to another. You can probably create something on your own or take one of the sample schemata that a vendor provides by default and adapt it to the other vendors. Or you can use something that is already there. When I searched for something that would fit me needs I came across the “Dell DVD Store Database Test Suite”. This provides a sample schema, a data generator and even a sample application for MySQL, Oracle, MSSQL and PostgreSQL. Perfect, lets see how this can be loaded into a PostgreSQL 9.5.2 database.

Once the ds21_postgresql.tar.gz and ds21.tar.gz archives are downloaded and extracted on the database host this is the content:

postgres@delldvdstorepostgresql:/var/tmp/ds2/ [DVDSTORE] ls -la
total 136
drwxr-xr-x. 5 postgres postgres  4096 Dec  2  2011 .
drwxrwxrwt. 3 root     root        63 Apr 12 10:51 ..
-rw-r--r--. 1 postgres postgres  5308 Aug 12  2010 CreateConfigFile.pl
drwxr-xr-x. 5 postgres postgres    73 May 31  2011 data_files
drwxr-xr-x. 2 postgres postgres  4096 Dec  2  2011 drivers
-rw-r--r--. 1 postgres postgres 30343 May 13  2011 ds2.1_Documentation.txt
-rw-r--r--. 1 postgres postgres 10103 Nov  9  2011 ds2_change_log.txt
-rw-r--r--. 1 postgres postgres  1608 Jul  1  2005 ds2_faq.txt
-rw-r--r--. 1 postgres postgres  2363 May  5  2011 ds2_readme.txt
-rw-r--r--. 1 postgres postgres  5857 Apr 21  2011 ds2_schema.txt
-rw-r--r--. 1 postgres postgres 18013 May 12  2005 gpl.txt
-rw-r--r--. 1 postgres postgres 32827 Nov  9  2011 Install_DVDStore.pl
drwxr-xr-x. 5 postgres postgres  4096 Apr 12 10:49 pgsqlds2

You can read the “ds2.1_Documentation.txt” for a detailed description on what can be done. I’ll show the quick way here. The first step is to create the “ds2″ user:

postgres=# create user ds2 superuser password 'ds2';
CREATE ROLE

postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of 
-----------+------------------------------------------------------------+-----------
 ds2       | Superuser                                                  | {}
 postgres  | Superuser, Create role, Create DB, Replication, Bypass RLS | {}

Having the user ready we can start to populate it by executing the “pgsqlds2_create_all.sh” script in the pgsqlds2 sub directory.

postgres@delldvdstorepostgresql:/var/tmp/ds2/pgsqlds2/ [DVDSTORE] chmod +x pgsqlds2_create_all.sh

As the script will try to connect as the postgres user for installing the plpgsql extension I did a little modification to the load script (the ds2 user is superuser anyway and is allowed to install the extension so why not use it):

#createlang plpgsql ds2
createlang -U ds2 plpgsql ds2

The output should be similar to this:

postgres@delldvdstorepostgresql:/var/tmp/ds2/pgsqlds2/ [DVDSTORE] ./pgsqlds2_create_all.sh
createlang: language "plpgsql" is already installed in database "ds2"
DROP DATABASE
CREATE DATABASE
ERROR:  role "ds2" already exists
ALTER ROLE
ERROR:  relation "customers" does not exist
ERROR:  relation "orders" does not exist
ERROR:  relation "orderlines" does not exist
ERROR:  relation "cust_hist" does not exist
ERROR:  relation "inventory" does not exist
ERROR:  relation "products" does not exist
DROP TABLE
DROP TABLE
ERROR:  relation "inventory" does not exist
DROP OWNED
DROP ROLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
INSERT 0 1
CREATE TABLE
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
CREATE FUNCTION
ALTER TABLE
COPY 10000
COPY 10000
ALTER TABLE
ALTER TABLE
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
COPY 1000
ALTER TABLE
ALTER TABLE
COPY 5083
COPY 5001
COPY 5164
COPY 4947
COPY 5022
COPY 5065
COPY 5010
COPY 4942
COPY 5010
COPY 5163
COPY 4992
COPY 4951
ALTER TABLE
ALTER TABLE
COPY 5083
COPY 5001
COPY 5164
COPY 4947
COPY 5022
COPY 5065
COPY 5010
COPY 4942
COPY 5010
COPY 5163
COPY 4992
COPY 4951
ALTER TABLE
ALTER TABLE
COPY 10000
ALTER TABLE
ALTER TABLE
COPY 10000
ALTER TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
ALTER TABLE
CREATE INDEX
ALTER TABLE
CREATE INDEX
ALTER TABLE
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE INDEX
CREATE FUNCTION
CREATE TRIGGER
 setval 
--------
     16
(1 row)

 setval 
--------
  20000
(1 row)

 setval 
--------
  12000
(1 row)

 setval 
--------
  10000
(1 row)

CREATE ROLE
GRANT
GRANT
GRANT
ANALYZE

You can ignore the errors at the beginning that’s fine (these are statement trying to disable and delete triggers for tables that have been already deleted).

So, what did we get?

postgres=# \c ds2
You are now connected to database "ds2" as user "postgres".
ds2=# \d
                  List of relations
 Schema |           Name           |   Type   | Owner 
--------+--------------------------+----------+-------
 public | categories               | table    | ds2
 public | categories_category_seq  | sequence | ds2
 public | cust_hist                | table    | ds2
 public | customers                | table    | ds2
 public | customers_customerid_seq | sequence | ds2
 public | inventory                | table    | ds2
 public | orderlines               | table    | ds2
 public | orders                   | table    | ds2
 public | orders_orderid_seq       | sequence | ds2
 public | products                 | table    | ds2
 public | products_prod_id_seq     | sequence | ds2
 public | reorder                  | table    | ds2
(12 rows)
ds2=# \di
                       List of relations
 Schema |          Name           | Type  | Owner |   Table    
--------+-------------------------+-------+-------+------------
 public | categories_pkey         | index | ds2   | categories
 public | customers_pkey          | index | ds2   | customers
 public | inventory_pkey          | index | ds2   | inventory
 public | ix_cust_hist_customerid | index | ds2   | cust_hist
 public | ix_cust_user_password   | index | ds2   | customers
 public | ix_cust_username        | index | ds2   | customers
 public | ix_order_custid         | index | ds2   | orders
 public | ix_orderlines_orderid   | index | ds2   | orderlines
 public | ix_prod_actor           | index | ds2   | products
 public | ix_prod_cat_special     | index | ds2   | products
 public | ix_prod_category        | index | ds2   | products
 public | ix_prod_special         | index | ds2   | products
 public | ix_prod_title           | index | ds2   | products
 public | orders_pkey             | index | ds2   | orders
 public | products_pkey           | index | ds2   | products
(15 rows)

ds2=# select oid from pg_roles where rolname = 'ds2' ;
  oid  
-------
 17093
(1 row)

ds2=# select proname,prolang::regclass from pg_proc where proowner = 17093;
      proname       | prolang 
--------------------+---------
 restock_order      | 13280
 new_customer       | 13280
 login              | 13280
 browse_by_category | 13280
 browse_by_actor    | 13280
 browse_by_title    | 13280
 purchase           | 13280
(7 rows)


ds2=# select tgname,tgrelid::regclass from pg_trigger;
            tgname            |  tgrelid   
------------------------------+------------
 RI_ConstraintTrigger_a_17160 | customers
 RI_ConstraintTrigger_a_17161 | customers
 RI_ConstraintTrigger_c_17162 | cust_hist
 RI_ConstraintTrigger_c_17163 | cust_hist
 RI_ConstraintTrigger_a_17166 | customers
 RI_ConstraintTrigger_a_17167 | customers
 RI_ConstraintTrigger_c_17168 | orders
 RI_ConstraintTrigger_c_17169 | orders
 RI_ConstraintTrigger_a_17172 | orders
 RI_ConstraintTrigger_a_17173 | orders
 RI_ConstraintTrigger_c_17174 | orderlines
 RI_ConstraintTrigger_c_17175 | orderlines
 restock                      | inventory
(13 rows)

Some tables, sequences, indexes, triggers and functions. Fine. How big is this database?

ds2=# select * from pg_size_pretty ( pg_database_size ('ds2'));
 pg_size_pretty 
----------------
 25 MB
(1 row)

Quite small. But the good thing with this “ds2″ sample application is that you can go for more data if you want. There is a perl script which can be used to generate any amount of data;

postgres@delldvdstorepostgresql:/var/tmp/ds2/ [DVDSTORE] pwd
/var/tmp/ds2
postgres@delldvdstorepostgresql:/var/tmp/ds2/ [DVDSTORE] chmod +x Install_DVDStore.pl

So, lets say I want to have a 1GB database. It is a easy as:

postgres@delldvdstorepostgresql:/var/tmp/ds2/ [DVDSTORE] ./Install_DVDStore.pl 
Please enter following parameters: 
***********************************
Please enter database size (integer expected) : 1000
Please enter whether above database size is in (MB / GB) : MB
Please enter database type (MSSQL / MYSQL / PGSQL / ORACLE) : PGSQL
Please enter system type on which DB Server is installed (WIN / LINUX) : LINUX
***********************************
***********************************
Initializing parameters...
***********************************
Database Size: 1000 
Database size is in MB 
Database Type is PGSQL 
System Type for DB Server is LINUX 
***********************************

Calculating Rows in tables!! 
Small size database (less than 1 GB) 
Ratio calculated : 100 
Customer Rows: 2000000 
Order Rows / month: 100000 
Product Rows: 1000000 

Creating CSV files....
Starting to create CSV data files.... 
For larger database sizes, it will take time.
Do not kill the script till execution is complete. 

Creating Customer CSV files!!! 
1 1000000 US S 0 
1000001 2000000 ROW S 0 

Customer CSV Files created!! 

Creating Orders, Orderlines and Cust_Hist csv files!!! 

Creating Order CSV file for Month jan !!! 
1 100000 jan S 1 0 1000000 2000000 

Creating Order CSV file for Month feb !!! 
100001 200000 feb S 2 0 1000000 2000000 

Creating Order CSV file for Month mar !!! 
200001 300000 mar S 3 0 1000000 2000000 

Creating Order CSV file for Month apr !!! 
300001 400000 apr S 4 0 1000000 2000000 

Creating Order CSV file for Month may !!! 
400001 500000 may S 5 0 1000000 2000000 

Creating Order CSV file for Month jun !!! 
500001 600000 jun S 6 0 1000000 2000000 

Creating Order CSV file for Month jul !!! 
600001 700000 jul S 7 0 1000000 2000000 

Creating Order CSV file for Month aug !!! 
700001 800000 aug S 8 0 1000000 2000000 

Creating Order CSV file for Month sep !!! 
800001 900000 sep S 9 0 1000000 2000000 

Creating Order CSV file for Month oct !!! 
900001 1000000 oct S 10 0 1000000 2000000 

Creating Order CSV file for Month nov !!! 
1000001 1100000 nov S 11 0 1000000 2000000 

Creating Order CSV file for Month dec !!! 
1100001 1200000 dec S 12 0 1000000 2000000 

All Order, Orderlines, Cust_Hist CSV files created !!! 

Creating Inventory CSV file!!!! 

Inventory CSV file created!!!! 

Creating product CSV file!!!! 

Product CSV file created!!!! 

Creating build script for PostgreSQL from templates... 

Template files are stored in respective build folders and the output files are also stored in same folder 

Template files are named with generic_template at end of their filename and the output files without _template at end 

Completed creating and writing build scripts for PostgreSQL database... 

All database build scripts(shell and sql) are dumped into their respective folders. 

These scripts are created from template files in same folders with '_generic_template' in their name. 

Scripts that are created from template files have '_' 1000 MB in their name. 

User can edit the sql script generated for customizing sql script for more DBFiles per table and change the paths of DBFiles.

Now Run CreateConfigFile.pl perl script in ds2 folder which will generate configuration file used as input to the driver program.

Once you now re-run the load script:

postgres@delldvdstorepostgresql:/var/tmp/ds2/pgsqlds2/ [DVDSTORE] pwd
/var/tmp/ds2/pgsqlds2
postgres@delldvdstorepostgresql:/var/tmp/ds2/pgsqlds2/ [DVDSTORE] ./pgsqlds2_create_all.sh

… you’ll have a database with size:

postgres=# select * from pg_size_pretty ( pg_database_size ('ds2'));
 pg_size_pretty 
----------------
 1741 MB
(1 row)

Not exactly 1GB but really cool. In one of the next posts we’ll do the same with an Oracle database.

 

Cet article The (almost) same sample schema for all major relational databases (1) – PostgreSQL est apparu en premier sur Blog dbi services.

Maintenance scenarios with EDB Failover Manager (2) – Primary node

$
0
0

In the last post I looked at how you can do maintenance operations on the standby node when you are working in a PostgreSQL cluster protected by EDB Failover Manager. In this post I’ll look on how you can do maintenance on the primary node (better: the node where the primary instance currently runs on). This requires slightly more work and attention. Lets go.

As a quick reminder this is the setup:

IP Description
192.168.22.243 Current PostgreSQL hot standby instance
192.168.22.245 Currernt PostgreSQL primary instance
192.168.22.244 EDB Failover Manager Witness Node + EDB BART
192.168.22.250 Virtual IP that is used for client connections to the master database

When we want to do maintenance on the current primary node this will require a fail over of the PostgreSQL instance. In addition the VIP shall fail over too to provide the clients the same address to connect as before the fail over. Lets check the current status of the fail over cluster:

postgres@edbbart:/home/postgres/ [pg950] efmstat 
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Master      192.168.22.245       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Standby     192.168.22.243       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.245 192.168.22.243

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/350000D0       
	Standby     192.168.22.243       0/350000D0       

	Standby database(s) in sync with master. It is safe to promote.

The last line is telling us that it is probably safe to promote. Consider these two cases:

  • Case 1: You want to perform a maintenance which requires the reboot the whole node
  • Case 2: You want to perform a maintenance which requires only the restart of the PostgreSQL instance on that node

It is important to distinguish the two cases because it will impact on how you have to deal with EDB Failover Manager. Lets see what happens in case one when we do a promote and then reboot the node. I’ll do the promote command on the witness node but it doesn’t really matter as you can execute it from any node in the fail over cluster:

-bash-4.2$ /usr/efm-2.0/bin/efm promote efm
Promote command accepted by local agent. Proceeding with promotion. Run the 'cluster-status' command for information about the new cluster state.

What happened. First lets check the cluster status:

-bash-4.2$ /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Idle        192.168.22.245       UP     UNKNOWN   
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.243       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.245 192.168.22.243

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.243       0/350001E0       

	No standby databases were found.

Idle Node Status (idle nodes ignored in XLog location comparisons):

	Address              XLog Loc         Info
	--------------------------------------------------------------
	192.168.22.245       0/350000D0       DB is not in recovery.

The old master is gone (Idle/UNKNOWN) and the old standby became the new master. You can double check this if you login to the new master and check if the instance is still in recovery mode:

postgres@edbppas:/home/postgres/ [PGSITE1] ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:6d:d8:b7 brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
       valid_lft 85491sec preferred_lft 85491sec
    inet6 fe80::a00:27ff:fe6d:d8b7/64 scope link 
       valid_lft forever preferred_lft forever
3: enp0s8:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:e4:19:ec brd ff:ff:ff:ff:ff:ff
    inet 192.168.22.243/24 brd 192.168.22.255 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet 192.168.22.250/24 brd 192.168.22.255 scope global secondary enp0s8:0
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:fee4:19ec/64 scope link 
       valid_lft forever preferred_lft forever
postgres@edbppas:/home/postgres/ [PGSITE1] sqh
psql.bin (9.5.0.5)
Type "help" for help.

postgres=# select * from pg_is_in_recovery();
 pg_is_in_recovery 
-------------------
 f
(1 row)

From the IP configuration output it is also proved that the VIP failed over to the new master node. What is the status of the old master instance?

postgres@ppasstandby:/home/postgres/ [PGSITE2] ip a
1: lo:  mtu 65536 qdisc noqueue state UNKNOWN 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:19:6f:0a brd ff:ff:ff:ff:ff:ff
    inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
       valid_lft 85364sec preferred_lft 85364sec
    inet6 fe80::a00:27ff:fe19:6f0a/64 scope link 
       valid_lft forever preferred_lft forever
3: enp0s8:  mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:ba:c0:6a brd ff:ff:ff:ff:ff:ff
    inet 192.168.22.245/24 brd 192.168.22.255 scope global enp0s8
       valid_lft forever preferred_lft forever
    inet6 fe80::a00:27ff:feba:c06a/64 scope link 
       valid_lft forever preferred_lft forever
postgres@ppasstandby:/home/postgres/ [PGSITE2] sqh
psql.bin (9.5.0.5)
Type "help" for help.

postgres=# select * from pg_is_in_recovery();                               
 pg_is_in_recovery 
-------------------
 f
(1 row)

This is dangerous, because: You now have two masters. If any of your applications uses the local IP address to connect then it would be still connected to the standby instance. Failover Manager created a new recovery.conf file though:

postgres@ppasstandby:/home/postgres/ [PGSITE2] cat $PGDATA/recovery.conf
# EDB Failover Manager
# This generated recovery.conf file prevents the db server from accidentally
# being restarted as a master since a failover or promotion has occurred
standby_mode = on
restore_command = 'echo 2>"recovery suspended on failed server node"; exit 1'

But as long as you do not restart the old primary instance the instance will accept modifications. If you restart:

2016-04-11 11:37:40.114 GMT - 8 - 3454 -  - @ LOCATION:  ReadRecord, xlog.c:3983
2016-04-11 11:37:40.114 GMT - 6 - 3452 -  - @ LOG:  00000: database system is ready to accept read only connections

… this can not do any harm anymore. But the required step to restart automatically by EDB Failover Manager is missing. It is left to you to perform an immediate restart of the old master instance to prevent the two master scenario. This should definitely be improved in EDB Failover Manager.

Once maintenance is finished and the old master node is rebooted what is the status of the cluster? Lets check:

[root@edbbart ~] /usr/edb-efm/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Master      192.168.22.243       UP     UP        
	Witness     192.168.22.244       UP     N/A       

Allowed node host list:
	192.168.22.244 192.168.22.243

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.243       0/37021258       

	No standby databases were found.

The information of the old master completely disappeared. So how can we recover from that and bring back the old configuration? The first step is to add the old master node back to the allowed hosts of the cluster:

[root@edbbart ~] /usr/edb-efm/bin/efm add-node efm 192.168.22.245
add-node signal sent to local agent.
[root@edbbart ~] 

This should result in the following output:

[root@edbbart ~] /usr/edb-efm/bin/efm cluster-status efm | grep -A 2 "Allowed"
Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Now we need to rebuild the old master as a new standby. This can be done in various ways, the two most common are to create a new basebackup of the new master or to use pg_rewind. I’ll us pg_rewind here. So to rebuild the old master as a new standby:

postgres@ppasstandby:/u02/pgdata/PGSITE2/ [PGSITE2] pg_rewind -D /u02/pgdata/PGSITE2/ --source-server="port=4445 host=192.168.22.243 user=postgres dbname=postgres"
servers diverged at WAL position 0/350000D0 on timeline 2
rewinding from last common checkpoint at 0/35000028 on timeline 2
Done!

Make sure your recovery.conf matches your environment;

postgres@ppasstandby:/u02/pgdata/PGSITE2/ [PGSITE2] cat recovery.conf
standby_mode = 'on'
primary_slot_name = 'standby1'
primary_conninfo = 'user=postgres password=admin123 host=192.168.22.243 port=4445 sslmode=prefer sslcompression=1'
recovery_target_timeline = 'latest'
trigger_file='/u02/pgdata/PGSITE2/trigger_file'

Start the new standby instance and check the log file:

2016-04-17 11:21:40.021 GMT - 1 - 2440 -  - @ LOG:  database system was interrupted while in recovery at log time 2016-04-17 11:09:28 GMT
2016-04-17 11:21:40.021 GMT - 2 - 2440 -  - @ HINT:  If this has occurred more than once some data might be corrupted and you might need to choose an earlier recovery target.
2016-04-17 11:21:40.554 GMT - 3 - 2440 -  - @ LOG:  entering standby mode
2016-04-17 11:21:40.608 GMT - 4 - 2440 -  - @ LOG:  redo starts at 0/35000098
2016-04-17 11:21:40.704 GMT - 5 - 2440 -  - @ LOG:  consistent recovery state reached at 0/37047858
2016-04-17 11:21:40.704 GMT - 6 - 2440 -  - @ LOG:  invalid record length at 0/37047858
2016-04-17 11:21:40.704 GMT - 4 - 2438 -  - @ LOG:  database system is ready to accept read only connections
2016-04-17 11:21:40.836 GMT - 1 - 2444 -  - @ LOG:  started streaming WAL from primary at 0/37000000 on timeline 3

So far for the database part. To bring back the EDB failover manager configuration we need to adjust the efm.nodes file on the new standby to include all the hosts in the configuration:

[root@ppasstandby efm-2.0] pwd
/etc/efm-2.0
[root@ppasstandby efm-2.0] cat efm.nodes 
# List of node address:port combinations separated by whitespace.
192.168.22.244:9998 192.168.22.243:9998 192.168.22.245:9998

Once this is done EDB Failover Manager can be restarted and the configuration is fine again:

[root@ppasstandby efm-2.0] systemctl start efm-2.0.service
[root@ppasstandby efm-2.0] /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Witness     192.168.22.244       UP     N/A       
	Standby     192.168.22.245       UP     UP        
	Master      192.168.22.243       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.245

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.243       0/37048540       
	Standby     192.168.22.245       0/37048540       

	Standby database(s) in sync with master. It is safe to promote.

Coming to the second scenario: When you do not need to reboot the server but only need to take down the master database for maintenance what are the steps to follow? As with scenario 1 you’ll have to promote to activate the standby database and immediately shutdown the old master:

[root@edbbart ~]# /usr/edb-efm/bin/efm promote efm
Promote command accepted by local agent. Proceeding with promotion. Run the 'cluster-status' command for information about the new cluster state.
[root@edbbart ~]# /usr/edb-efm/bin/efm cluster-status efm 
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Idle        192.168.22.243       UP     UNKNOWN   
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/37048730       

	No standby databases were found.

Idle Node Status (idle nodes ignored in XLog location comparisons):

	Address              XLog Loc         Info
	--------------------------------------------------------------
	192.168.22.243       UNKNOWN          Connection refused. Check that the hostname and port are correct and that the postmaster is accepting TCP/IP connections.

Now you can do your maintenance operations and once you finished rebuild the old master as a new standby:

postgres@edbppas:/u02/pgdata/PGSITE1/ [PGSITE1] pg_rewind -D /u02/pgdata/PGSITE1/ --source-server="port=4445 host=192.168.22.245 user=postgres dbname=postgres"
servers diverged at WAL position 0/37048620 on timeline 3
rewinding from last common checkpoint at 0/37048578 on timeline 3
Done!

postgres@edbppas:/u02/pgdata/PGSITE1/ [PGSITE1] cat recovery.conf
standby_mode = 'on'
primary_slot_name = 'standby1'
primary_conninfo = 'user=postgres password=admin123 host=192.168.22.245 port=4445 sslmode=prefer sslcompression=1'
recovery_target_timeline = 'latest'
trigger_file='/u02/pgdata/PGSITE1/trigger_file'

Once you restarted the instance EDB Failover Manager shows:

[root@edbbart ~]# /usr/edb-efm/bin/efm cluster-status efm 
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Master      192.168.22.245       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Idle        192.168.22.243       UP     UNKNOWN   

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	(List is empty.)

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/37068EF0       

	No standby databases were found.

Idle Node Status (idle nodes ignored in XLog location comparisons):

	Address              XLog Loc         Info
	--------------------------------------------------------------
	192.168.22.243       0/37068EF0       DB is in recovery.

The new standby is detected as “in recovery” but still shows “UNKNOWN”. To fix this execute the “resume” command on the new standby and then check the cluster status again:

[root@edbppas ~] /usr/edb-efm/bin/efm resume efm
Resume command successful on local agent.
[root@edbppas ~] /usr/edb-efm/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Standby     192.168.22.243       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/37068EF0       
	Standby     192.168.22.243       0/37068EF0       

	Standby database(s) in sync with master. It is safe to promote.

Everything back to normal operations.
Conclusion: It depends on what exactly you want to do to get the failover cluster configuration back to normal operations. The steps itself are easy, the main issue is to perform them in the right order. Having that documented is a must as you’ll probably not do these kind of tasks every day.

 

Cet article Maintenance scenarios with EDB Failover Manager (2) – Primary node est apparu en premier sur Blog dbi services.

Maintenance scenarios with EDB Failover Manager (3) – Witness node

$
0
0

In the last posts ( Maintenance scenarios with EDB Failover Manager (1) – Standby node , Maintenance scenarios with EDB Failover Manager (2) – Primary node ) we looked at how to perform maintenance operations on the master as well as on the standby node in a failover cluster managed by EDB Failober Manager. What is still open is how to perform maintenance operations on the witness node. So, lets go.

The current status of the cluster is fine:

postgres@edbbart:/home/postgres/ [pg950] /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Standby     192.168.22.243       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/380000D0       
	Standby     192.168.22.243       0/380000D0       

	Standby database(s) in sync with master. It is safe to promote.

Probably the only situations you’ll need to take care of is when you want to reboot the witness node for any reason or when you need to take down the efm service. What happens when you stop the service on the witness?

[root@edbbart ~] systemctl stop efm-2.0.service

Checking the status on either the master or the standby node:

[root@ppasstandby efm-2.0] /usr/efm-2.0/bin/efm cluster-status efm
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Standby     192.168.22.243       UP     UP        
	Master      192.168.22.245       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/380000D0       
	Standby     192.168.22.243       0/380000D0       

	Standby database(s) in sync with master. It is safe to promote.

The witness disappeared. How to bring it back? Re-create the efm.nodes file on the witness node:

[root@edbbart efm-2.0] pwd
/etc/efm-2.0
[root@edbbart efm-2.0] cat efm.nodes
# List of node address:port combinations separated by whitespace.
192.168.22.243:9998 192.168.22.244:9998 192.168.22.245:9998

Start the service:

[root@edbbart efm-2.0] systemctl start efm-2.0.service

… and you’ll be back in business:

[root@edbbart efm-2.0] /usr/edb-efm/bin/efm cluster-status efm 
Cluster Status: efm
Automatic failover is disabled.

	Agent Type  Address              Agent  DB       Info
	--------------------------------------------------------------
	Master      192.168.22.245       UP     UP        
	Witness     192.168.22.244       UP     N/A       
	Standby     192.168.22.243       UP     UP        

Allowed node host list:
	192.168.22.244 192.168.22.243 192.168.22.245

Standby priority host list:
	192.168.22.243

Promote Status:

	DB Type     Address              XLog Loc         Info
	--------------------------------------------------------------
	Master      192.168.22.245       0/380000D0       
	Standby     192.168.22.243       0/380000D0       

	Standby database(s) in sync with master. It is safe to promote.

What do you need to do in case you need to reboot? Exactly the same :) Quite easy when you want to do maintenance on the witness node.

Btw: If you want you can meet us at the Swiss PGDAY, Agenda here

 

Cet article Maintenance scenarios with EDB Failover Manager (3) – Witness node est apparu en premier sur Blog dbi services.

Connecting your PostgreSQL instance to a MariaDB/MySQL instance

$
0
0

Some time ago I blogged on how to connect your PostgreSQL instance to an Oracle instance (here and here). In this post I’ll do the same with a MariaDB/MySQL instance.

For connecting PostgreSQL to MariaDB/Mysql we’ll need the foreign data wrapper for MySQL. As the foreign data wrapper for MySQL requires the MySQL/MariaDB client and development libraries lets install these first:

postgres@pgreporting:/home/postgres/ [pg952] sudo yum install -y mariadb-libs mariadb-devel

Make sure that you have mysql_config as well as pg_config in your PATH:

postgres@pgreporting:/home/postgres/ [pg952] which pg_config
/u01/app/postgres/product/95/db_2/bin/pg_config
postgres@pgreporting:/home/postgres/ [pg952] which mysql_config
/usr/bin/mysql_config

Once you are ready it is straight forward:

postgres@pgreporting:/var/tmp/ [pg952] unzip mysql_fdw-master.zip
postgres@pgreporting:/var/tmp/mysql_fdw-master/ [pg952] make USE_PGXS=1
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME=\"libmysqlclient.so\" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o connection.o connection.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME=\"libmysqlclient.so\" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o option.o option.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME=\"libmysqlclient.so\" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o deparse.o deparse.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME=\"libmysqlclient.so\" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o mysql_query.o mysql_query.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I/usr/include/mysql -D _MYSQL_LIBNAME=\"libmysqlclient.so\" -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o mysql_fdw.o mysql_fdw.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -shared -o mysql_fdw.so connection.o option.o deparse.o mysql_query.o mysql_fdw.o -L/u01/app/postgres/product/95/db_2/lib -Wl,--as-needed -Wl,-rpath,'/u01/app/postgres/product/95/db_2/lib',--enable-new-dtags  
postgres@pgreporting:/var/tmp/mysql_fdw-master/ [pg952] make USE_PGXS=1 install
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/lib'
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension'
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension'
/bin/install -c -m 755  mysql_fdw.so '/u01/app/postgres/product/95/db_2/lib/mysql_fdw.so'
/bin/install -c -m 644 .//mysql_fdw.control '/u01/app/postgres/product/95/db_2/share/extension/'
/bin/install -c -m 644 .//mysql_fdw--1.0.sql  '/u01/app/postgres/product/95/db_2/share/extension/'

From here on it is the usual steps. Create the extension:

postgres= create extension mysql_fdw;
CREATE EXTENSION
postgres= \dx
                            List of installed extensions
   Name    | Version |   Schema   |                   Description                    
-----------+---------+------------+--------------------------------------------------
 mysql_fdw | 1.0     | public     | Foreign data wrapper for querying a MySQL server
 plpgsql   | 1.0     | pg_catalog | PL/pgSQL procedural language
(2 rows)

postgres=

Make sure you are allowed to connect to your MySQL instance from where your PostgreSQL runs on. In my case I did this in the MariaDB instance:

MariaDB [DS2]> grant all on *.* TO 'web'@'192.168.22.39' identified by "web";
Query OK, 0 rows affected (0.00 sec)

MariaDB [DS2]> SHOW GLOBAL VARIABLES LIKE 'PORT';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| port          | 3306  |
+---------------+-------+
1 row in set (0.00 sec)

Once this is ready we can proceed on the PostgreSQL instance:

CREATE SERVER mysql_server FOREIGN DATA WRAPPER mysql_fdw  OPTIONS (host '192.168.22.41', port '3306');
CREATE USER MAPPING FOR postgres SERVER mysql_server OPTIONS (username 'web', password 'web');
CREATE schema mysql;
CREATE FOREIGN TABLE mysql.customer(
 CUSTOMERID           bigint
,FIRSTNAME            varchar(50)
,LASTNAME             varchar(50)
,ADDRESS1             varchar(50)
,ADDRESS2             varchar(50)
,CITY                 varchar(50)
,STATE                varchar(50)
,ZIP                  bigint
,COUNTRY              varchar(50)
,REGION               int
,EMAIL                varchar(50)
,PHONE                varchar(50)
,CREDITCARDTYPE       bigint   
,CREDITCARD           varchar(50)
,CREDITCARDEXPIRATION varchar(50)
,USERNAME             varchar(50)
,PASSWORD             varchar(50)
,AGE                  int
,INCOME               bigint
,GENDER               varchar(1)
)
SERVER mysql_server
     OPTIONS (dbname 'DS2', table_name 'CUSTOMERS');

postgres= select count(*) from mysql.customer;
 count  
--------
 200000
(1 row)

postgres=# 

If you wonder where the remote table comes from then have a look at the previous post where the schema is setup in the MariaDB/MySQL instance.

Even better, as with the oracle_fdw (if you are on PostgreSQL 9.5+), you can import the foreign schema:

postgres= import foreign schema "DS2" from server mysql_server into mysql;
IMPORT FOREIGN SCHEMA
postgres= show search_path;
   search_path   
-----------------
 "$user", public
(1 row)
postgres= set search_path= 'mysql';
SET
postgres= \d
               List of relations
 Schema |    Name    |     Type      |  Owner   
--------+------------+---------------+----------
 mysql  | CATEGORIES | foreign table | postgres
 mysql  | CUSTOMERS  | foreign table | postgres
 mysql  | CUST_HIST  | foreign table | postgres
 mysql  | INVENTORY  | foreign table | postgres
 mysql  | ORDERLINES | foreign table | postgres
 mysql  | ORDERS     | foreign table | postgres
 mysql  | PRODUCTS   | foreign table | postgres
 mysql  | REORDER    | foreign table | postgres
 mysql  | customer   | foreign table | postgres
(9 rows)

postgres=# select count(*) from "ORDERS";
INFO:  Successfully connected to MySQL database DS2 at server 192.168.22.41 via TCP/IP with cipher  (server version: 5.5.47-MariaDB, protocol version: 10) 
 count  
--------
 120000
(1 row)

One command and everything is there :)

 

Cet article Connecting your PostgreSQL instance to a MariaDB/MySQL instance est apparu en premier sur Blog dbi services.

Interested in the most advanced open source database? Where you can meet us in June …

$
0
0

Are you interested in what PostgreSQL can do for you? You can join us at the following events in June:

We will be doing the “Transform your database tour” together with EnterpriseDB in Zurich and Geneva (German and French/English):

Selection_026

More details here.

And we’ll be at the Swiss PGDAY in Rapperswil (German speaking, mostly):

Selection_025

There will be plenty of time for discussions and networking. Looking forward to see you.

 

Cet article Interested in the most advanced open source database? Where you can meet us in June … est apparu en premier sur Blog dbi services.

Connecting your PostgreSQL instance to a Microsoft SQL Server instance

$
0
0

In the last posts I looked at how you can connect Oracle and MariaDB/MySQL to a PostgreSQL instance. In this post I’ll do the same with a MS SQL Server instance.

What you need before you can start is a library that implements the Tabular Data Stream protocol. For Linux based systems there is FreeTDS. Installation is quite easy:

postgres@pgreporting:/var/tmp/ [pg952] wget ftp://ftp.freetds.org/pub/freetds/stable/freetds-patched.tar.gz
postgres@pgreporting:/var/tmp/ [pg952] ls
freetds-patched.tar.gz
postgres@pgreporting:/var/tmp/ [pg952] tar -axf freetds-patched.tar.gz
postgres@pgreporting:/var/tmp/freetds-0.95.95/ [pg952] ls
aclocal.m4  CMakeLists.txt  configure     doc              INSTALL       m4           mkinstalldirs  samples      vms
AUTHORS     compile         configure.ac  freetds.conf     install-sh    Makefile.am  NEWS           src          win32
autogen.sh  config.guess    COPYING       freetds.spec     interfaces    Makefile.in  Nmakefile      tds.dox
BUGS        config.rpath    COPYING.LIB   freetds.spec.in  locales.conf  misc         PWD.in         test-driver
ChangeLog   config.sub      depcomp       include          ltmain.sh     missing      README         TODO
postgres@pgreporting:/var/tmp/freetds-0.95.95/ [pg952] ./configure 
postgres@pgreporting:/var/tmp/freetds-0.95.95/ [pg952] make
postgres@pgreporting:/var/tmp/freetds-0.95.95/ [pg952] sudo make install

At this point in time it is advisable to test the connection to the MS SQL Server instance. FreeTDS will install a default configuration which you can adjust to fit your environment:

postgres@pgreporting:/var/tmp/freetds-0.95.95/ [pg952] cat /usr/local/etc/freetds.conf
#   $Id: freetds.conf,v 1.12 2007-12-25 06:02:36 jklowden Exp $
#
# This file is installed by FreeTDS if no file by the same 
# name is found in the installation directory.  
#
# For information about the layout of this file and its settings, 
# see the freetds.conf manpage "man freetds.conf".  

# Global settings are overridden by those in a database
# server specific section
[global]
        # TDS protocol version
;	tds version = 4.2

	# Whether to write a TDSDUMP file for diagnostic purposes
	# (setting this to /tmp is insecure on a multi-user system)
;	dump file = /tmp/freetds.log
;	debug flags = 0xffff

	# Command and connection timeouts
;	timeout = 10
;	connect timeout = 10
	
	# If you get out-of-memory errors, it may mean that your client
	# is trying to allocate a huge buffer for a TEXT field.  
	# Try setting 'text size' to a more reasonable limit 
	text size = 64512

# A typical Sybase server
[egServer50]
	host = symachine.domain.com
	port = 5000
	tds version = 5.0

# A typical Microsoft server
[mssql]
	host = 192.168.22.102
	port = 1433
        database = ds2
	tds version = 7.3

The last block specifies the parameters for connecting to my MS SQL Server instance. Lets try:

postgres@pgreporting:/home/postgres/ [pg952] tsql -I /usr/local/etc/freetds.conf -S mssql -U ds2user -P xxxxx -o v
locale is "LC_CTYPE=en_US.UTF-8;LC_NUMERIC=de_CH.UTF-8;LC_TIME=en_US.UTF-8;LC_COLLATE=en_US.UTF-8;LC_MONETARY=de_CH.UTF-8;LC_MESSAGES=en_US.UTF-8;LC_PAPER=de_CH.UTF-8;LC_NAME=de_CH.UTF-8;LC_ADDRESS=de_CH.UTF-8;LC_TELEPHONE=de_CH.UTF-8;LC_MEASUREMENT=de_CH.UTF-8;LC_IDENTIFICATION=de_CH.UTF-8"
locale charset is "UTF-8"
using default charset "UTF-8"
1> select count(*) from sys.databases;
2> go

using TDS version 7.3
5
(1 row affected)
using TDS version 7.3

Cool, works. If you wonder where the ds2user comes from then check this post.

Once this works we can proceed with installing the foreign data wrapper for Sybase / MS SQL Server which is quite easy as well:

postgres@pgreporting:/home/postgres/ [PGREP] git clone https://github.com/tds-fdw/tds_fdw.git
Cloning into 'tds_fdw'...
remote: Counting objects: 588, done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 588 (delta 11), reused 0 (delta 0), pack-reused 561
Receiving objects: 100% (588/588), 242.61 KiB | 0 bytes/s, done.
Resolving deltas: 100% (335/335), done.
postgres@pgreporting:/home/postgres/ [PGREP] cd tds_fdw
postgres@pgreporting:/home/postgres/tds_fdw/ [PGREP] PATH=$PGHOME:$PATH make USE_PGXS=1
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I./include/ -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/tds_fdw.o src/tds_fdw.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I./include/ -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/options.o src/options.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -I./include/ -I. -I./ -I/u01/app/postgres/product/95/db_2/include/server -I/u01/app/postgres/product/95/db_2/include/internal -D_GNU_SOURCE -I/usr/include/libxml2   -c -o src/deparse.o src/deparse.c
gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -O2 -fpic -shared -o tds_fdw.so src/tds_fdw.o src/options.o src/deparse.o -L/u01/app/postgres/product/95/db_2/lib -Wl,--as-needed -Wl,-rpath,'/u01/app/postgres/product/95/db_2/lib',--enable-new-dtags  -lsybdb 
cp sql/tds_fdw.sql sql/tds_fdw--2.0.0-alpha.1.sql
cp README.md README.tds_fdw.md
postgres@pgreporting:/home/postgres/tds_fdw/ [PGREP] sudo PATH=$PGHOME/bin:$PATH make USE_PGXS=1 install
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/lib'
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension'
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/extension'
/bin/mkdir -p '/u01/app/postgres/product/95/db_2/share/doc/extension'
/bin/install -c -m 755  tds_fdw.so '/u01/app/postgres/product/95/db_2/lib/tds_fdw.so'
/bin/install -c -m 644 .//tds_fdw.control '/u01/app/postgres/product/95/db_2/share/extension/'
/bin/install -c -m 644 .//sql/tds_fdw--2.0.0-alpha.1.sql  '/u01/app/postgres/product/95/db_2/share/extension/'
/bin/install -c -m 644 .//README.tds_fdw.md '/u01/app/postgres/product/95/db_2/share/doc/extension/'

Continue with the usual steps to create the extension in your PostgreSQL instance:

postgres= create extension tds_fdw;
CREATE EXTENSION
postgres= \dx
                                                List of installed extensions
   Name    |    Version    |   Schema   |                                    Description                                    
-----------+---------------+------------+-----------------------------------------------------------------------------------
 mysql_fdw | 1.0           | public     | Foreign data wrapper for querying a MySQL server
 plpgsql   | 1.0           | pg_catalog | PL/pgSQL procedural language
 tds_fdw   | 2.0.0-alpha.1 | public     | Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)
(3 rows)

If this succeeds we’ll need to create the foreign server and the user mapping:

postgres= create server mssql_svr foreign data wrapper tds_fdw options ( servername '192.168.22.102', port '1433',  database 'ds2', tds_version '7.3', msg_handler 'notice' );
CREATE schema ds2_mssql;
CREATE USER MAPPING FOR postgres SERVER mssql_svr  OPTIONS (username 'ds2user', password 'xxxxx');

As I am lazy I want to import the foreign the schema for not needing to specify each table on my own:

postgres=# IMPORT FOREIGN SCHEMA ds2 FROM SERVER mssql_svr into ds2_mssql;
ERROR:  foreign-data wrapper "tds_fdw" does not support IMPORT FOREIGN SCHEMA

Hm, not available. This is tracked here and might be available in future versions. No other choice than to do some hand work:

create foreign table ds2_mssql.customers (
 CUSTOMERID            int
,FIRSTNAME             varchar(50)
,LASTNAME              varchar(50)
,ADDRESS1              varchar(50)
,ADDRESS2              varchar(50)
,CITY                  varchar(50)
,STATE                 varchar(50)
,ZIP                   int
,COUNTRY               varchar(50)
,REGION                int
,EMAIL                 varchar(50)
,PHONE                 varchar(50)
,CREDITCARDTYPE        int
,CREDITCARD            varchar(50)
,CREDITCARDEXPIRATION  varchar(50)
,USERNAME              varchar(50)
,PASSWORD              varchar(50)
,AGE                   int
,INCOME                int
,GENDER                varchar(50))
SERVER mssql_svr
    OPTIONS (table 'dbo.customers', row_estimate_method 'showplan_all');

Lets see if it works:

postgres=# select count(*) from ds2_mssql.customers;
 count  
--------
 200000
(1 row)

Perfect. Have fun getting data from MS SQL Server.

 

Cet article Connecting your PostgreSQL instance to a Microsoft SQL Server instance est apparu en premier sur Blog dbi services.

Happy birthday PostgreSQL


A look at PostgreSQL 9.6 – The wait interface

$
0
0

For a long time there was no real wait interface in PostgreSQL core. Now, with the upcoming 9.6, pg_stat_activity was extended to provide more meaningful information for what a session is currently waiting on. If you are interested in reading through the history: It all started here. Lets have a look at it by doing same simple tests.

When I want to see what a session is waiting for I’ll at least need to sessions: One doing some work and the other for querying the wait event information. Obviously I’ll need to know my backend process identifier which I then can use to query pg_stat_activity. PostgreSQL provides a function to get the backend process id:

(postgres@[local]:5432) [postgres] > select * from pg_backend_pid();
 pg_backend_pid 
----------------
           3048
(1 row)

Using this session lets create a table and populate it with some rows:

(postgres@[local]:5432) [postgres] > create table t1 (a int);
CREATE TABLE
(postgres@[local]:5432) [postgres] > insert into t1 (a) values ( generate_series(1,1000000) );
INSERT 0 1000000

If you are fast enough to switch to the other session and query for the wait event you’ll see this:

(postgres@[local]:5432) [postgres] > select wait_event_type,wait_event from pg_stat_activity where pid = 3048;
 wait_event_type |  wait_event  
-----------------+--------------
 LWLockNamed     | WALWriteLock
(1 row)

So, what does this mean? The documentation gives the answer:

  • LWLockNamed: The backend is waiting for a specific named lightweight lock. Each such lock protects a particular data structure in shared memory. wait_event will contain the name of the lightweight lock.
  • WALWriteLock: Waiting for WAL buffers to be written to disk.

Makes sense: Changed data needs to be written to the WAL.

Another example: In one session I’ll start a transaction and update one row in the table without closing/committing the same:

(postgres@[local]:5432) [postgres] > begin;
BEGIN
Time: 0.103 ms
(postgres@[local]:5432) [postgres] > update t1 set a = 2 where a = 1;
UPDATE 1
Time: 56.086 ms
(postgres@[local]:5432) [postgres] > 

In a third session lets try to update the same row:

(postgres@[local]:5432) [postgres] > select * from pg_backend_pid();
 pg_backend_pid 
----------------
           3397
(1 row)

Time: 0.220 ms
(postgres@[local]:5432) [postgres] > update t1 set a = 2 where a = 1;

This should cause a wait event, but which one?

(postgres@[local]:5432) [postgres] > select wait_event_type,wait_event from pg_stat_activity where pid = 3397;
 wait_event_type |  wait_event   
-----------------+---------------
 Lock            | transactionid
(1 row)

Another event type and another event:

  • Lock: The backend is waiting for a heavyweight lock. Heavyweight locks, also known as lock manager locks or simply locks, primarily protect SQL-visible objects such as tables. However, they are also used to ensure mutual exclusion for certain internal operations such as relation extension. wait_event will identify the type of lock awaited.
  • transactionid: Waiting for a transaction to finish

In PostgreSQL DDL is transactional, too, so we should be able to create another wait event when we try to modify the table in one session:

(postgres@[local]:5432) [postgres] > begin;
BEGIN
Time: 0.085 ms
(postgres@[local]:5432) [postgres] > alter table t1 add column b int;
ALTER TABLE
Time: 0.318 ms
(postgres@[local]:5432) [postgres] > 

… and then try to update a row in another session:

(postgres@[local]:5432) [postgres] > update t1 set a = 2 where a = 1;

What is reported?

(postgres@[local]:5432) [postgres] > select wait_event_type,wait_event from pg_stat_activity where pid = 3397;
 wait_event_type | wait_event 
-----------------+------------
 Lock            | relation
(1 row)
  • Lock: The backend is waiting for a heavyweight lock. Heavyweight locks, also known as lock manager locks or simply locks, primarily protect SQL-visible objects such as tables. However, they are also used to ensure mutual exclusion for certain internal operations such as relation extension. wait_event will identify the type of lock awaited.
  • relation: Waiting to acquire a lock on a relation.

Currently there are 68 documented wait events and I am sure more will show up during the next releases. This is a huge help if you need to troubleshoot sessions because now you do not need extensions any more and do not need to compile PostgreSQL with dynamic tracing.

 

Cet article A look at PostgreSQL 9.6 – The wait interface est apparu en premier sur Blog dbi services.

A look at PostgreSQL 9.6 – progress reporting for VACUUM operations

$
0
0

Vacuum in PostgreSQL is one of the most important points to consider when managing a PostgreSQL instance. Usually vacuum is running in the background and just gets the job done. But, as always, there are situations when you need to get a closer look at what is going on. PostgreSQL 9.6 (currently in Beta1) introduced a new view which allows to see the progress of the vacuum worker processes. Lets have a short look at it.

To have something available for vacuum to do lets generate some data:

(postgres@[local]:5432) [postgres] > create table t1 ( a int, b varchar(40), c timestamp );
CREATE TABLE
insert into t1 ( a, b, c )
select aa, bb, cc
  from generate_series(1,10000000) aa
     , md5(aa::varchar) bb
     , now() cc;
NSERT 0 10000000

Vacuuming this table right now does not make any sense as there are no tuples to cleanup. We’ll need to delete or update some data for this. Before doing this I’ll disable autovacuum so I can kick it off manually when I am ready with my data:

(postgres@[local]:5432) [postgres] > show autovacuum;
 autovacuum 
------------
 on
(1 row)

(postgres@[local]:5432) [postgres] > alter system set autovacuum='off';
ALTER SYSTEM
(postgres@[local]:5432) [postgres] > select * from pg_reload_conf();
 pg_reload_conf 
----------------
 t
(1 row)

(postgres@[local]:5432) [postgres] > 

Having a look at the log file confirms that the autovacuum launcher process was shut down:

2016-05-17 07:33:02.648 CEST - 4 - 2703 -  - @ LOG:  received SIGHUP, reloading configuration files
2016-05-17 07:33:02.653 CEST - 5 - 2703 -  - @ LOG:  parameter "autovacuum" changed to "off"
2016-05-17 07:33:02.655 CEST - 2 - 2709 -  - @ LOG:  autovacuum launcher shutting down

Time to delete some data from the test table:

delete from t1
 where mod(a,7) = 0
;
DELETE 1428571

This should result in some dead tuples which we can check by querying pg_stat_user_tables:

(postgres@[local]:5432) [postgres] > select n_tup_del
                                          , n_live_tup
                                          , n_dead_tup 
                                       from pg_stat_user_tables 
                                      where relname='t1';
 n_tup_del | n_live_tup | n_dead_tup 
-----------+------------+------------
   1571428 |    8571429 |    1428571
(1 row)

The amount of dead tuples corresponds to the number of rows we deleted. Now we can start vacuum on the table and check the new pg_stat_progress_vacuum for what is going on in a seconds session.

Session 1:

postgres@[local]:5432) [postgres] > vacuum verbose t1;

Session 2:

(postgres@[local]:5432) [postgres] > \x
Expanded display is on.
(postgres@[local]:5432) [postgres] > select * from pg_stat_progress_vacuum;

The result of the above command (executed twice with some seconds in between) is:

(postgres@[local]:5432) [postgres] > select * from pg_stat_progress_vacuum;
-[ RECORD 1 ]------+--------------
pid                | 3051
datid              | 13322
datname            | postgres
relid              | 16388
phase              | scanning heap
heap_blks_total    | 93458
heap_blks_scanned  | 1568
heap_blks_vacuumed | 1567
index_vacuum_count | 0
max_dead_tuples    | 291
num_dead_tuples    | 16


(postgres@[local]:5432) [postgres] > select * from pg_stat_progress_vacuum;
-[ RECORD 1 ]------+--------------
pid                | 3051
datid              | 13322
datname            | postgres
relid              | 16388
phase              | scanning heap
heap_blks_total    | 93458
heap_blks_scanned  | 90618
heap_blks_vacuumed | 90617
index_vacuum_count | 0
max_dead_tuples    | 291
num_dead_tuples    | 15

Pretty cool. Now we can estimate how long the operation will take or how much work is already done (when heap_blks_scanned comes close to heap_blks_total work should almost be done). According to the documentation and to the thread on hackers this is only the first view providing progress information…more will probably come in future releases.

 

Cet article A look at PostgreSQL 9.6 – progress reporting for VACUUM operations est apparu en premier sur Blog dbi services.

A look at PostgreSQL 9.6 – Killing idle transactions automatically

$
0
0

A common issue with databases: The guy at floor 2 did some work on the database and then rashly left for lunch because the lady on floor 1 is already waiting for him. Unfortunately he did not close his transaction and now his session is blocking others. In PostgreSQL this might be even worse as all tuples modified by this transaction are not available for vacuum until the transaction is either committed or aborted. In PostgreSQL 9.6 there will be a way to minimize this risk.

As always with PostgreSQL: If someone wants to add something to PostgreSQL core it starts with a mail tread. The result was a new parameter called idle_in_transaction_session_timeout. Lets see how this works.

The default value of idle_in_transaction_session_timeout is 0, which means disabled:

(postgres@[local]:5432) [postgres] > show idle_in_transaction_session_timeout;
 idle_in_transaction_session_timeout 
-------------------------------------
 0
(1 row)

I’ll set it to one minute…

(postgres@[local]:5432) [postgres] > alter system set idle_in_transaction_session_timeout='1min';
ALTER SYSTEM

Lets create a user:

(postgres@[local]:5432) [postgres] > create user u login password 'u';
CREATE ROLE

Using that user login and start a transaction without doing any further work:

postgres@centos7:/home/postgres/ [PG1] psql postgres u -W
Password for user u: 
psql (9.6beta1 dbi services build)
Type "help" for help.

(u@[local]:5432) [postgres] > begin;
BEGIN

Btw: Being idle in transaction is reported in the process list, too:

(postgres@[local]:5432) [postgres] > \! ps -ef | grep idle
postgres  2712  2702  0 08:12 ?        00:00:00 postgres: postgres postgres [local] idle
postgres  3072  2702  0 08:14 ?        00:00:00 postgres: u postgres [local] idle in transaction
postgres  3412  2711  0 08:17 pts/0    00:00:00 sh -c ps -ef | grep idle
postgres  3414  3412  0 08:17 pts/0    00:00:00 grep idle

After one minute this is reported in the log file:

2016-05-18 08:17:32.352 CEST - 1 - 3072 - [local] - u@postgres FATAL:  terminating connection due to idle-in-transaction timeout

An attempt to do anything in the session that user u opened results in:

(u@[local]:5432) [postgres] > select 1;
FATAL:  terminating connection due to idle-in-transaction timeout
server closed the connection unexpectedly
        This probably means the server terminated abnormally
        before or while processing the request.
The connection to the server was lost. Attempting reset: Succeeded.

Works well … no more killing sessions because guys head for lunch :)

 

Cet article A look at PostgreSQL 9.6 – Killing idle transactions automatically est apparu en premier sur Blog dbi services.

A look at PostgreSQL 9.6 – psql gexec

$
0
0

This little, but powerful, enhancement that it made it in PostgreSQL 9.6 is probably nothing a application can benefit of. But it can be huge saving for people doing maintenance operations on a PostgreSQL instance. It is the addition of the “gexec” meta command to psql. If you want to read where this comes from and how it evolved you can read the mail thread on hackers.

As always lets do a little demo. Lets say you have a simple sql that produces some “create table” statements:

select 'create table tt'||gen||' (a int, b int )'||';'
  from generate_series(1,20) gen;

When you run this the output will be:

              ?column?              
------------------------------------
 create table tt1 (a int, b int );
 create table tt2 (a int, b int );
 create table tt3 (a int, b int );
 create table tt4 (a int, b int );
 create table tt5 (a int, b int );
 create table tt6 (a int, b int );
 create table tt7 (a int, b int );
 create table tt8 (a int, b int );
 create table tt9 (a int, b int );
 create table tt10 (a int, b int );
 create table tt11 (a int, b int );
 create table tt12 (a int, b int );
 create table tt13 (a int, b int );
 create table tt14 (a int, b int );
 create table tt15 (a int, b int );
 create table tt16 (a int, b int );
 create table tt17 (a int, b int );
 create table tt18 (a int, b int );
 create table tt19 (a int, b int );
 create table tt20 (a int, b int );

If you now want to execute the generated statements you could get rid of the heading and all other formatting and spool it into a file. You then can execute the file and you are done. You could even do that in one script all together. Now, with gexec, there is much more elegant way to do this:

select 'create table tt'||gen||' (a int, b int )' 
  from generate_series(1,20) gen
\gexec

What this does is: Each generated command from the select is executed in the order the statement returns them:

postgres@[local]:5432) [postgres] > select 'create table tt'||gen||' (a int, b int )' 
                                      from generate_series(1,20) gen
\gexec
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE
CREATE TABLE

All the tables are there. You can image yourself what you could do with that :) While reading the documentation I additionally learned about the format function today. If you, for example, want to create an index on every column of the above tables you could do:

with tabs as
( select 'tt'||a tab
    from generate_series(1,20) a
)
select format('create index on %I',b.tab)||format('(%I)' ,c.attname)
  from tabs b
     , pg_attribute c
 where c.attrelid = b.tab::varchar::regclass
   and c.attnum > 0
  order by 1
\gexec
CREATE INDEX
CREATE INDEX
...
CREATE INDEX
CREATE INDEX

Easy and fast. Of course you can drop the tables the same way:

select 'drop table tt'||gen
  from generate_series(1,20) gen
\gexec

Really nice feature. Have fun …

 

Cet article A look at PostgreSQL 9.6 – psql gexec est apparu en premier sur Blog dbi services.

Which parameter changes do require a restart of my PostgreSQL instance?

$
0
0

Starting wiht PostgreSQL 9.4 you can change parameters in postgresql.conf with the “alter system” command in psql. In principle every parameter can be changed that way but not every parameter is applied immediately. Some of the parameters require a reload others require a complete restart of the instance. But which of these parameter require what? How can you know which method you have to use for which parameter?

The first thing to know is that parameter changes you trigger by using “alter system” are not written to postgresql.conf which is the parameter file for the instance. Instead parameter changes are written to postgresql.auto.conf. Lets do a simple example by changing the work_mem parameter:

(postgres@[local]:5432) [postgres] > show work_mem;
 work_mem 
----------
 32MB
(1 row)

Time: 0.204 ms
(postgres@[local]:5432) [postgres] > alter system set work_mem='16MB';
ALTER SYSTEM
Time: 320.400 ms

The initial setting was 32MB and I changed that to 16MB. Does it go into effect immediately?

(postgres@[local]:5432) [postgres] > show work_mem;
 work_mem 
----------
 32MB
(1 row)

No. Before looking at how we can make this parameter change going live lets look at what was written to posstgresql.auto.conf:

postgres@centos7:/u02/pgdata/PG1/ [PG1] cat postgresql.auto.conf 
# Do not edit this file manually!
# It will be overwritten by ALTER SYSTEM command.
work_mem = '16MB'

So we have the new setting in the postgresql.auto.conf file. What about postgresql.conf?

postgres@centos7:/u02/pgdata/PG1/ [PG1] grep work_mem postgresql.conf 
work_mem=32MB
maintenance_work_mem=64MB

We still see the old value there and this never gets changed. What does that mean? When the server starts it reads postgresql.conf and in addition the values from postgresql.auto.conf are applied and the values for parameters in postgresql.conf are overwritten/replaced by the values for the parameters in postgresql.auto.conf. This is important to undertand. If you change the value of a parameter in postgresql.conf but you have the same parameter specified in postgresql.auto.conf you will never succeed:

postgres@centos7:/u02/pgdata/PG1/ [PG1] sed -i 's/work_mem=32MB/work_mem=8MB/g' postgresql.conf 
postgres@centos7:/u02/pgdata/PG1/ [PG1] grep work_mem postgresql.conf 
work_mem=8MB
maintenance_work_mem=64MB

I changed the parameter in postgresql.conf to 8MB and then I’ll restart the instance and check the value of the parameter:

postgres@centos7:/u02/pgdata/PG1/ [PG1] pg_ctl -D /u02/pgdata/PG1/ restart -m fast
postgres@centos7:/u02/pgdata/PG1/ [PG1] psql
(postgres@[local]:5432) [postgres] > show work_mem;
 work_mem 
----------
 16MB
(1 row)

There is a value of 16MB now and not 8MB what I did write to the postgresql.conf file. Conclusion: Parameters set in postgresql.conf are overwritten if the same parameter is set in postgresql.auto.conf.

Back to the original question: How can I know what action a parameter change requires to go into effect? The answer is pg_settings:

(postgres@[local]:5432) [postgres] > \d pg_settings
     View "pg_catalog.pg_settings"
     Column      |  Type   | Modifiers 
-----------------+---------+-----------
 name            | text    | 
 setting         | text    | 
 unit            | text    | 
 category        | text    | 
 short_desc      | text    | 
 extra_desc      | text    | 
 context         | text    | 
 vartype         | text    | 
 source          | text    | 
 min_val         | text    | 
 max_val         | text    | 
 enumvals        | text[]  | 
 boot_val        | text    | 
 reset_val       | text    | 
 sourcefile      | text    | 
 sourceline      | integer | 
 pending_restart | boolean | 

The important column is the “context” column. By knowing the context you know what you need to do:

(postgres@[local]:5432) [postgres] > select context from pg_settings where name = 'work_mem';
 context 
---------
 user
(1 row)

In this case it means that every user can change the setting for the local session. Do we need to restart if we change it globally?

(postgres@[local]:5432) [postgres] > alter system set work_mem='12MB';
ALTER SYSTEM
Time: 316.481 ms
(postgres@[local]:5432) [postgres] > select pending_restart from pg_settings where name = 'work_mem';
 pending_restart 
-----------------
 f
(1 row)

No. So a reload should be fine:

(postgres@[local]:5432) [postgres] > select * from pg_reload_conf();
 pg_reload_conf 
----------------
 t
(1 row)

Time: 4.158 ms
(postgres@[local]:5432) [postgres] > show work_mem;
 work_mem 
----------
 12MB
(1 row)

Now we have it applied and we didn’t need to restart. What about changing parameters that reuqire a restart?

(postgres@[local]:5432) [postgres] > show port;
 port 
------
 5432
(1 row)

Time: 0.177 ms
(postgres@[local]:5432) [postgres] > alter system set port=5555;
ALTER SYSTEM
Time: 311.963 ms
(postgres@[local]:5432) [postgres] > select pending_restart from pg_settings where name = 'port';
 pending_restart 
-----------------
 f
(1 row)

Hm. Changing the port for sure requires a restart. Why does pg_settings tell us that we do not need to restart? Lets try a reload and see what happens:

(postgres@[local]:5432) [postgres] > select * from pg_reload_conf();
 pg_reload_conf 
----------------
 t
(1 row)

When you look at the log file for the last action you’ll notice this:

2016-06-10 08:11:23.987 CEST - 4 - 3111 -  - @ LOG:  received SIGHUP, reloading configuration files
2016-06-10 08:11:23.988 CEST - 5 - 3111 -  - @ LOG:  parameter "port" cannot be changed without restarting the serve

So at least here we can see that we need to restart for our parameter to be applied. What does pg_settings now show?

(postgres@[local]:5432) [postgres] > select pending_restart from pg_settings where name = 'port';
 pending_restart 
-----------------
 t
(1 row)

Now it shows true. This means you first need to reload PostgreSQL for the pending_restart column being updated (This is also true for the work_mem test above. We have just been lucky in that case). Conclusion: For whatever parameter you change do a reload afterwards and then check pg_settings if you need to additionally restart the instance.

 

Cet article Which parameter changes do require a restart of my PostgreSQL instance? est apparu en premier sur Blog dbi services.

EM13c and postgres plugin

$
0
0

As an Oracle DBA I use Enterprise Manager to monitor Oracle databases at my client’s sites. I also administer more and more Postgres databases. I decided to download the Blue Medora plugin in order to monitor the postgresql databases with Enterprise Manager 13c, and to avoid to have different monitoring tools for each kinf of database.

Once you have downloaded the Blue Medora plugin for EM13c, you have to unzip it:

oracle@vmtestoraCC13c:/home/oracle/psi/ [rdbms12102] unzip bm.em.xpgs_12.1.0.2.0_2.0.3.zip
Archive:  bm.em.xpgs_12.1.0.2.0_2.0.3.zip
  inflating: bm.em.xpgs_12.1.0.2.0_2.0.3.opar
......

Then like other plugins, you have to import it in the OMS (Oracle Management Server):

oracle@vmtestoraCC13c:/home/oracle/psi/ [oms13c] emcli import_update
 -file=/home/oracle/psi/bm.em.xpgs_12.1.0.2.0_2.0.3.opar -omslocal
Processing update: Plug-in - PostgreSQL Monitoring
Successfully uploaded the update to Enterprise Manager. 
Use the Self Update Console to manage this update.

Once imported, from the Extensibility plugin page, we can display the PostgreSQL plugin:

pp1

We have to deploy the plugin to the OMS:

pp2

The next step consists now to deploy the plugin on an agent where there is an existing postgres environment, we select the adequate agent and we select Continue:

pp3

The postgresql plugin is successfully deployed to the agent:

pp4

Once the plugin is deployed, we need to add a postgres database target. I used the Add Target Declaratively and choosed Postgresql Database as Target Type:

pp5

In the next screen you enter the target name and useful informations such as hostname, login, password and port number:

pp6

Finally the postgresql database target has been added successfully:

pp7

Once the configuration phase finished, let’s have a look over how EM13c works with postgresql !

The newly postgresql database target exist in EM13c:

pp8

We have the same menus as we are used for Oracle database targets:

pp18

Now let’s try to create a monitoring template for postgresql database. From the EM13c Monitoring template menu, choose create:

pp9

Choose Target Type and select PosgreSQL database:

pp10

Enter the monitoring template name and a description:

pp11

You have the possibility to define thresholds for metrics:

pp12

Select Ok and the DBI_DB_POSTGRES is created.

Finally we apply the template to our postgres database as follows, we select the postgressql database and we select Apply:

pp13

The Home postgres EM13c page displays more informations:

pp14

The postgresql monitoring offers a lot of monitoring solutions:

pp161

 

We have the possibility to diplay the table or indices details:

pp15

Another good point is the possibility to use the reports. For example the target availability:

pp17

You can also create incident rules in the same way you did it for Oracle databases. Creating incident rules about Availability, Metric Alert or Metric Errors allows you the possibility to have incidents created and to receive alerts when something goes wrong in your posgresql database.

pp16

Once you have correctly configured your incident rules and their events, when you stop your postgres database, an incident is created and you receive a mail :=)

pp19

Deploying the Blue Medora’s plugin in order to administer your postgresql databases withe Enterprise Manager 13c will help you to administer heteregeneous databases environment. Furthermore you can use monitoring templates and incident rules.

 

 

 

 

 

 

 

 

 

 

 

 

 

Cet article EM13c and postgres plugin est apparu en premier sur Blog dbi services.

Swiss PGDAY 2016, Slides are online


PostgreSQL as a central reporting hub? – Yes, of course

$
0
0

For every client we do projects for there usually are database systems from various vendors. In most places you at least find some Oracle and MS SQL Server databases. Probably somewhere there are even some MySQL/MariaDB or PostgreSQL instance running. The Oracle and MS SQL Server stuff almost always is there because vendors require it. For MySQL/MariaDB the common use case are web applications, ticketing systems and home grown developments. At some point in time there might be a requirement to centralize important data of all these databases into a central reporting hub. The more data you have the more there is a requirement to analyze it and to create reports that drive some sorts of decisions. PostgreSQL is very well prepared to assist in this. If you have read the last posts about connecting your PostgreSQL instance to either Oracle, MS SQL Server, MariaDB/MySQL or even other PostgreSQL instances you might already know into what direction this post will go.

This is a sample use case: There is a requirement to centralize all the sales figures of a company into one big reporting database. The (simplified) database landscape in this company looks exactly as described above:

pg_reporting_1

There is one Oracle database, one MS SQL Server instance, one MariaDB/MySQL instance and one PostgreSQL instance. Each of them holds some sales figures which shall be integrated into the reporting database. For the demo setup I use the Dell DVD Store Database sample schema. You can read how to set this up for:

As the goal is to have a PostgreSQL instance as a central reporting hub the desired database landscape will approximately look like this:

pg_reporting_2

Lets assume all the foreign data wrappers are already setup in the central PostgreSQL instance:

(postgres@[local]:4445) [postgres] > \dx
                                                 List of installed extensions
     Name     |    Version    |   Schema   |                                    Description                                    
--------------+---------------+------------+-----------------------------------------------------------------------------------
 mysql_fdw    | 1.0           | public     | Foreign data wrapper for querying a MySQL server
 oracle_fdw   | 1.1           | public     | foreign data wrapper for Oracle access
 plpgsql      | 1.0           | pg_catalog | PL/pgSQL procedural language
 postgres_fdw | 1.0           | ds2_oracle | foreign-data wrapper for remote PostgreSQL servers
 tds_fdw      | 2.0.0-alpha.1 | public     | Foreign data wrapper for querying a TDS database (Sybase or Microsoft SQL Server)

In addition lets assume all the foreign servers and all the user mappings are there and are working:

(postgres@[local]:4445) [postgres] > select srvname,srvoptions from pg_foreign_server;
   srvname    |                                      srvoptions                                       
--------------+---------------------------------------------------------------------------------------
 mysql_server | {host=192.168.22.41,port=3306}
 mssql_svr    | {servername=192.168.22.102,port=1433,database=ds2,tds_version=7.3,msg_handler=notice}
 oracle_srv   | {dbserver=//192.168.22.42/DELLDVD}
 postgres_srv | {host=192.168.22.40,port=5432,dbname=ds2}
(4 rows)

(postgres@[local]:4445) [postgres] > select * from pg_user_mappings;
 umid  | srvid |   srvname    | umuser | usename  |               umoptions                
-------+-------+--------------+--------+----------+----------------------------------------
 65547 | 65546 | mysql_server |     10 | postgres | {username=web,password=web}
 65587 | 65586 | mssql_svr    |     10 | postgres | {username=ds2user,password=ds2}
 65615 | 65614 | oracle_srv   |     10 | postgres | {user=DS2,password=ds2}
 65676 | 65675 | postgres_srv |     10 | postgres | {user=ds2,password=ds2}

As the central reporting database is already connected to all the other database systems how could you organize the fetching of the data? One approach is to create a separate schema for each of the foreign databases and one additional schema that combines the data:

(postgres@[local]:4445) [postgres] > create schema ds2_mssql;
(postgres@[local]:4445) [postgres] > create schema ds2_oracle;
(postgres@[local]:4445) [postgres] > create schema ds2_mysql;
(postgres@[local]:4445) [postgres] > create schema ds2_postgresql;
(postgres@[local]:4445) [postgres] > create schema ds2_combined;
(postgres@[local]:4445) [postgres] > \dn
      List of schemas
      Name      |  Owner   
----------------+----------
 ds2_combined   | postgres
 ds2_mssql      | postgres
 ds2_mysql      | postgres
 ds2_oracle     | postgres
 ds2_postgresql | postgres
 public         | postgres
(6 rows)

The next step is to create the foreign tables we want to work with.

For Oracle, MySQL/MariaDB and PostgreSQL we can use the import foreign schema command:

postgres=# import foreign schema "DS2" from server oracle_srv into ds2_oracle;
IMPORT FOREIGN SCHEMA
postgres= import foreign schema "DS2" from server mysql_srv into ds2_mysql;
IMPORT FOREIGN SCHEMA
postgres= import foreign schema "public" from server postgres_srv into ds2_postgresql;
IMPORT FOREIGN SCHEMA

For MS SQL Server we need to specify the foreign tables on our own (there is a feature request to implement import foreign schema):

create foreign table ds2_mssql.orders 
  ( orderid numeric not null
  , orderdate timestamp(0) without time zone not null
  , customerid numeric                                
  , netamount numeric(12,2) not null 
  , tax numeric(12,2) not null 
  , totalamount numeric(12,2) not null 
  )
SERVER mssql_svr
OPTIONS (table 'dbo.orders', row_estimate_method 'showplan_all');

create foreign table ds2_mssql.orderlines
  ( orderlineid numeric not null 
  , orderid numeric not null 
  , prod_id numeric not null 
  , quantity numeric not null 
  , orderdate timestamp(0) without time zone not null 
  )
SERVER mssql_svr
OPTIONS (table 'dbo.orderlines', row_estimate_method 'showplan_all');

Having all the foreign tables available we can start to work with the data either by creating materialized views:

create materialized view ds2_combined.mv_orders as
  select * from ds2_mssql.orders
  union all
  select * from ds2_mysql."ORDERS"
  union all
  select * from ds2_oracle.orders
  union all
  select * from ds2_postgresql.orders
  with no data;
refresh materialized view ds2_combined.mv_orders with data;

… or by importing the data into PostgreSQL and then build reports on top of that:

BEGIN;
  insert into ds2_combined.orders select * from ds2_mssql.orders;
  insert into ds2_combined.orders select * from ds2_mysql."ORDERS";
  insert into ds2_combined.orders select * from ds2_oracle.orders;
  insert into ds2_combined.orders select * from ds2_postgresql.orders;
END;
BEGIN;
  insert into ds2_combined.orderlines 
         select * from ds2_mssql.orderlines;
  insert into ds2_combined.orderlines 
         select * from ds2_mysql."ORDERLINES";
  insert into ds2_combined.orderlines 
         select * from ds2_oracle.orderlines;
  insert into ds2_combined.orderlines 
         select * from ds2_postgresql.orderlines;
END;

Having all the data locally available you can do whatever you want with it. Have fun with reporting on your data …

Btw: The source for this was a session at the Swiss PGDAY 2016. You can download the slides there.

 

Cet article PostgreSQL as a central reporting hub? – Yes, of course est apparu en premier sur Blog dbi services.

Getting started with Ansible – Installing OS packages, creating groups and users

$
0
0

It has been quite a while since the first post in this series: “Getting started with Ansible – Preparations“. If you recap from the initial post Ansible was running on the control host and this simple Ansible command:

ansible postgres-servers -a "/bin/echo 11" -f 5

… was successfully executed against the “postgres-servers” group. So far, so good. Getting Ansible up and running for just this would not be very usefull, so lets see where we might go from here.

When you start to think on what you want to automate you should start to think on how you want to organize your Ansible stuff. The documentation provides some guidelines which might or might not fit your needs. For the scope of this series lets stick to what the documentation is recommeding as one possible way to go. The directory layout on the control host will then be:

[ansible@ansiblecontrol ~]$ sudo mkdir /opt/ansible
[ansible@ansiblecontrol ~]$ sudo chown ansible:ansible /opt/ansible
[ansible@ansiblecontrol ~]$ touch /opt/ansible/development                  # the inventory file for the development hosts      
[ansible@ansiblecontrol ~]$ touch /opt/ansible/staging                      # the inventory file for the staging hosts
[ansible@ansiblecontrol ~]$ touch /opt/ansible/production                   # the inventory file for the production hosts
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common                 # a role valid for "common" stuff
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/tasks
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/handlers
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/templates
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/files
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/vars
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/common/meta
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver    # a role vaild for the PostgreSQL stuff
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/tasks
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/handlers
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/templates
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/files
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/vars
[ansible@ansiblecontrol ~]$ mkdir /opt/ansible/roles/postgresqldbserver/meta

The concept of roles is explained in the documentation and you should definitely read that. We’ll come back to this later.

For now let’s place our two PostgreSQL hosts into the “development” inventory:

[ansible@ansiblecontrol ~]$ echo "[postgresql-servers]" >> /opt/ansible/development
[ansible@ansiblecontrol ~]$ echo "192.168.22.171" >> /opt/ansible/development
[ansible@ansiblecontrol ~]$ echo "192.168.22.172" >> /opt/ansible/development

Passing our new inventory file to Ansible we should be able to perform the same simple task as in the first post:

[ansible@ansiblecontrol ~]$ ansible -i /opt/ansible/development postgresql-servers -a "/bin/echo 11"
192.168.22.172 | SUCCESS | rc=0 >>
11

192.168.22.171 | SUCCESS | rc=0 >>
11

Ok, fine, this still works. When it comes to PostgreSQL one of the first steps when we want to install from source is to install all the operating system packages which are required. How could we do that with Ansible?

The initial step is to tell Ansible where to look for our roles. This is done by specifying the “roles_path” configuration parameter in the ansible.cfg configuration file:

[ansible@ansiblecontrol ~]$ cat /etc/ansible/ansible.cfg | grep roles | grep -v "#"
roles_path    = /opt/ansible/roles

From here on we need to setup our role by creating an initial “site.yml” file:

[ansible@ansiblecontrol ansible]$ cat roles/postgresqldbserver/site.yml 
---
# This playbook deploys a single PostgreSQL instance from the source code

- hosts: postgresql-servers
  become: true
  become_user: root

  roles:
    - postgresqldbserver

You can see from the above that the “postgresql-servers” group is referenced. Additionally notice the “become” and the “become_user” flags. As we’re going to use yum to install the packages we need a way to become root on the target system and this is how you can instruct Ansible to do so.
Time to specify on how we want to install the packages. This is quite easy as well:

[ansible@ansiblecontrol ansible]$ cat roles/postgresqldbserver/tasks/main.yml 
---
- name: Install PostgreSQL dependencies
  yum: name={{item}} state=present
  with_items:
   - gcc
   - openldap-devel
   - python-devel
   - readline-devel
   - openssl-devel
   - redhat-lsb
   - bison
   - flex
   - perl-ExtUtils-Embed
   - zlib-devel
   - crypto-utils
   - openssl-devel
   - pam-devel
   - libxml2-devel
   - libxslt-devel
   - tcl
   - tcl-devel
   - openssh-clients
   - bzip2
   - net-tools
   - wget
   - screen
   - ksh

What did we do here? We created our first task. We tell Ansible to use “yum” to install our “items” (which are the packages we want to install). You can check the documentation for more information on the yum module.

Lets see if it works and we can execute our first task on both PostgreSQL nodes:

[ansible@ansiblecontrol ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.171]
ok: [192.168.22.172]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
changed: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
changed: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

PLAY RECAP *********************************************************************
192.168.22.171             : ok=2    changed=1    unreachable=0    failed=0   
192.168.22.172             : ok=2    changed=1    unreachable=0    failed=0   

Cool, we just installed all the dependencies on both nodes with one Ansible command. We additionally want an operating system group for our PostgreSQL deployment so we add the following lines to the playbook:

- name: Add PostgreSQL operating system group
  group: name=postgressomegroup state=present

Execute the playbook again:

[ansible@ansiblecontrol ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

TASK [postgresqldbserver : Add PostgreSQL operating system group] **************
changed: [192.168.22.171]
changed: [192.168.22.172]

PLAY RECAP *********************************************************************
192.168.22.171             : ok=3    changed=1    unreachable=0    failed=0   
192.168.22.172             : ok=3    changed=1    unreachable=0    failed=0   

We did not change any of the packages but added the group. Lets add the PostgreSQL operating system user by adding these lines to the playbook:

- name: Add PostgreSQL operating system user
  user: name=postgres comment="PostgreSQL binaries owner" group=postgres

Execute again:

[ansible@ansiblecontrol ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

TASK [postgresqldbserver : Add PostgreSQL operating system group] **************
changed: [192.168.22.171]
changed: [192.168.22.172]

TASK [postgresqldbserver : Add PostgreSQL operating system user] ***************
changed: [192.168.22.171]
changed: [192.168.22.172]

PLAY RECAP *********************************************************************
192.168.22.171             : ok=4    changed=2    unreachable=0    failed=0   
192.168.22.172             : ok=4    changed=2    unreachable=0    failed=0   

Really cool and simple. Just to prove lets connect to one of the nodes and check if the postgres user really is there:

[root@ansiblepg2 ~] id -a postgres
uid=1001(postgres) gid=1001(postgres) groups=1001(postgres)
[root@ansiblepg2 ~] 

Perfect. In the next post we’ll install the PostgreSQL binaries.

For you reference this is the playbook as it looks now:

[ansible@ansiblecontrol ansible]$ cat roles/postgresqldbserver/tasks/main.yml
---
- name: Install PostgreSQL dependencies
  yum: name={{item}} state=present
  with_items:
   - gcc
   - openldap-devel
   - python-devel
   - readline-devel
   - openssl-devel
   - redhat-lsb
   - bison
   - flex
   - perl-ExtUtils-Embed
   - zlib-devel
   - crypto-utils
   - openssl-devel
   - pam-devel
   - libxml2-devel
   - libxslt-devel
   - tcl
   - tcl-devel
   - openssh-clients
   - bzip2
   - net-tools
   - wget
   - screen
   - ksh

- name: Add PostgreSQL operating system group
  group: name=postgressomegroup state=present

- name: Add PostgreSQL operating system user
  user: name=postgres comment="PostgreSQL binaries owner" group=postgres
 

Cet article Getting started with Ansible – Installing OS packages, creating groups and users est apparu en premier sur Blog dbi services.

Getting started with Ansible – Download the PostgreSQL sources, compile and install

$
0
0

In the last post in this series we looked at how you can instruct Ansible to install packages on the operating system using the yum module and how you can create groups and users by using the group and the user modules. In this post we’ll look at how you can download the PostgreSQL sources, compile and then finally install the binaries by extending our existing playbook.

If you remember the last post our current Ansible playbook looks like this:

[ansible@ansiblecontrol ansible]$ pwd
/opt/ansible
[ansible@ansiblecontrol ansible]$ cat roles/postgresqldbserver/tasks/main.yml 
---
- name: Install PostgreSQL dependencies
  yum: name={{item}} state=present
  with_items:
   - gcc
   - openldap-devel
   - python-devel
   - readline-devel
   - openssl-devel
   - redhat-lsb
   - bison
   - flex
   - perl-ExtUtils-Embed
   - zlib-devel
   - crypto-utils
   - openssl-devel
   - pam-devel
   - libxml2-devel
   - libxslt-devel
   - tcl
   - tcl-devel
   - openssh-clients
   - bzip2
   - net-tools
   - wget
   - screen
   - ksh

- name: Add PostgreSQL operating system group
  group: name=postgressomegroup state=present

- name: Add PostgreSQL operating system user
  user: name=postgres comment="PostgreSQL binaries owner" group=postgres

Basically we have three tasks:

  • Install the required operating system packages
  • Create the PostgreSQL operating system group
  • Create the PostgreSQL operating system user

The next task we want Ansible to do is to download the PostgreSQL sources. In this example we’ll download from the official PostgreSQL servers but if you do not have connectivity to the outside world this can be a local server in your company’s network as well. The module we’ll use for that is get_url_module. All we need to do is to add the following lines to our playbook:

- name: Download the PostgreSQL 9.5.3 sources
  get_url: url=https://ftp.postgresql.org/pub/source/v9.5.3/postgresql-9.5.3.tar.bz2 dest=/var/tmp mode=0755

Once we execute the playbook again:

[ansible@ansiblecontrol ~]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

TASK [postgresqldbserver : Add PostgreSQL operating system group] **************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Add PostgreSQL operating system user] ***************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Download the PostgreSQL 9.5.3 sources] **************
changed: [192.168.22.171]
changed: [192.168.22.172]

PLAY RECAP *********************************************************************
192.168.22.171             : ok=5    changed=1    unreachable=0    failed=0   
192.168.22.172             : ok=5    changed=1    unreachable=0    failed=0   

The sources are available on the PostgreSQL hosts:

[root@ansiblepg1 ~] ls /var/tmp/post*
/var/tmp/postgresql-9.5.3.tar.bz2

Now we need to do some scripting as there is no pre-defined module for installing PostgreSQL from source. Here is a very basic script to do that:

#!/usr/bin/bash
PGSOURCE="/var/tmp/postgresql-9.5.3.tar.bz2"
PGUSER="postgres"
PGGROUP="postgres"
PGHOME="/u01/app/postgres/product/95/db_3"
SEGSIZE=2
BLOCKSIZE=8
mkdir -p /u01/app
chown ${PGUSER}:${PGGROUP} /u01/app
su - ${PGUSER} -c "cd /var/tmp/; tar -axf ${PGSOURCE}"
su - ${PGUSER} -c "cd /var/tmp/postgresql-9.5.3; ./configure --prefix=${PGHOME} \
            --exec-prefix=${PGHOME} \
            --bindir=${PGHOME}/bin \
            --libdir=${PGHOME}/lib \
            --sysconfdir=${PGHOME}/etc \
            --includedir=${PGHOME}/include \
            --datarootdir=${PGHOME}/share \
            --datadir=${PGHOME}/share \
            --with-pgport=5432 \
            --with-perl \
            --with-python \
            --with-tcl \
            --with-openssl \
            --with-pam \
            --with-ldap \
            --with-libxml \
            --with-libxslt \
            --with-segsize=${SEGSIZE} \
            --with-blocksize=${BLOCKSIZE} \
            --with-wal-segsize=16  \
            --with-extra-version=\" dbi services build\""
su - ${PGUSER} -c "cd /var/tmp/postgresql-9.5.3; make world"
su - ${PGUSER} -c "cd /var/tmp/postgresql-9.5.3; make install"
su - ${PGUSER} -c "cd /var/tmp/postgresql-9.5.3/contrib; make install"
rm -rf /var/tmp/postgresql*

Place a file with this contents under the files directory of our role:

roles/postgresqldbserver/files/install_pg953.sh

There is another Ansible module called copy which we now can use to copy the file from our roles directory to the target server. All we need to do is to add the following lines to our playbook:

- name: Copy PostgreSQL install script to targets
  copy: src=install_pg953.sh dest=/var/tmp/install_pg953.sh owner=postgres group=postgres mode="u=rwx"

Once we execute the playbook the file is distributed to all targets (here the check for the first node):

[root@ansiblepg1 ~] ls /var/tmp/install*
/var/tmp/install_pg953.sh

The only thing we need to do from now on to get PostgreSQL installed on the target system is to exexute this file. How can we do that? Very easy by using the shell module. Add these lines to the playbook:

- name: Compile and install PostgreSQL
  shell: /var/tmp/install_pg953.sh >> /var/tmp/install_pg_log
  args:
    executable: /usr/bin/bash

… re-execute the playbook:

[ansible@ansiblecontrol ansible]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

TASK [postgresqldbserver : Add PostgreSQL operating system group] **************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Add PostgreSQL operating system user] ***************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Download the PostgreSQL 9.5.3 sources] **************
changed: [192.168.22.172]
changed: [192.168.22.171]

TASK [postgresqldbserver : Copy PostgreSQL install script to targets] **********
ok: [192.168.22.171]
ok: [192.168.22.172]

TASK [postgresqldbserver : Compile and install PostgreSQL] *********************
changed: [192.168.22.171]
changed: [192.168.22.172]

PLAY RECAP *********************************************************************
192.168.22.171             : ok=7    changed=2    unreachable=0    failed=0   
192.168.22.172             : ok=7    changed=2    unreachable=0    failed=0   

… and we are done. Just to prove it:

[root@ansiblepg1 ~] /u01/app/postgres/product/95/db_3/bin/psql --version
psql (PostgreSQL) 9.5.3 dbi services build
[root@ansiblepg2 ~] /u01/app/postgres/product/95/db_3/bin/psql --version
psql (PostgreSQL) 9.5.3 dbi services build

PostgreSQL is installed and ready to create a new database cluster (which is the topic for the next post).

Btw: The two steps of copying the script to the targets and then execute it can be combined into one step by using the script module.
Btw2: Of course you might do the same with Oracle, Mysql, MongoDB, Cassandra, …

 

Cet article Getting started with Ansible – Download the PostgreSQL sources, compile and install est apparu en premier sur Blog dbi services.

Getting started with Ansible – Creating the PostgreSQL instance

$
0
0

In the last three posts we did the initial Ansible setup, installed the operating system packages, created the PostgreSQL group and user and downloaded, compiled and installed the PostgreSQL binaries from source. In this post we’ll look at how we can use Ansible to create our first PostgreSQL instance.

As a reminder this is our current playbook:

[ansible@ansiblecontrol ansible]$ pwd
/opt/ansible
[ansible@ansiblecontrol ansible]$ cat roles/postgresqldbserver/tasks/main.yml 
---
- name: Install PostgreSQL dependencies
  yum: name={{item}} state=present
  with_items:
   - gcc
   - openldap-devel
   - python-devel
   - readline-devel
   - openssl-devel
   - redhat-lsb
   - bison
   - flex
   - perl-ExtUtils-Embed
   - zlib-devel
   - crypto-utils
   - openssl-devel
   - pam-devel
   - libxml2-devel
   - libxslt-devel
   - tcl
   - tcl-devel
   - openssh-clients
   - bzip2
   - net-tools
   - wget
   - screen
   - ksh

- name: Add PostgreSQL operating system group
  group: name=postgressomegroup state=present

- name: Add PostgreSQL operating system user
  user: name=postgres comment="PostgreSQL binaries owner" group=postgres

- name: Download the PostgreSQL 9.5.3 sources
  get_url: url=https://ftp.postgresql.org/pub/source/v9.5.3/postgresql-9.5.3.tar.bz2 dest=/var/tmp mode=0755

- name: Copy PostgreSQL install script to targets
  copy: src=install_pg953.sh dest=/var/tmp/install_pg953.sh owner=root group=root mode="u=rwx"

- name: Compile and install PostgreSQL
  shell: /var/tmp/install_pg953.sh >> /var/tmp/install_pg_log
  args:
    executable: /usr/bin/bash

What we need now is an additional task which does the creation of the PostgreSQL cluster on disk. As with the installation from source we’ll need to do some scripting for this. Here is a very basic script for doing this:

#!/usr/bin/bash

PGUSER="postgres"
PGGROUP="postgres"
DATADIRECTORY="/u02/pgdata/PG1"
XLOGLOCATION="/u03/pgdata/PG1"
PGHOME="/u01/app/postgres/product/95/db_3/"
POSTGRESDBPASSWORD="postgres"

mkdir -p ${DATADIRECTORY}
mkdir -p ${XLOGLOCATION}
chown ${PGUSER}:${PGGROUP} ${DATADIRECTORY}
chown ${PGUSER}:${PGGROUP} ${XLOGLOCATION}

su - ${PGUSER} -c "echo ${POSTGRESDBPASSWORD} > /var/tmp/tmp_pwd"
su - ${PGUSER} -c "${PGHOME}/bin/initdb -D ${DATADIRECTORY} --pwfile=/var/tmp/tmp_pwd -X ${XLOGLOCATION} -k"

rm -f /var/tmp/tmp_pwd

su - ${PGUSER} -c "${PGHOME}/bin/pg_ctl -D ${DATADIRECTORY} start"

As with the PostgreSQL installation script we’ll put this into the “files” directory of our “postgresqldbserver” role:

[ansible@ansiblecontrol ansible]$ ls roles/postgresqldbserver/files/
create_pg953_cluster.sh  install_pg953.sh

We’ll use the same logic again and add two new tasks to our existing playbook:

- name: Copy the PostgreSQL cluster creation script to the targets
  copy: src=create_pg953_cluster.sh dest=/var/tmp/create_pg953_cluster.sh owner=root group=root mode="u=rwx"

- name: Create and start the PostgreSQL instance
  shell: /var/tmp/create_pg953_cluster.sh >> /var/tmp/create_pg_cluster.log
  args:
    executable: /usr/bin/bash

Once the playbook is executed again:

[ansible@ansiblecontrol ansible]$ ansible-playbook -i /opt/ansible/development /opt/ansible/roles/postgresqldbserver/site.yml

PLAY [postgresql-servers] ******************************************************

TASK [setup] *******************************************************************
ok: [192.168.22.171]
ok: [192.168.22.172]

TASK [postgresqldbserver : Install PostgreSQL dependencies] ********************
ok: [192.168.22.172] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])
ok: [192.168.22.171] => (item=[u'gcc', u'openldap-devel', u'python-devel', u'readline-devel', u'openssl-devel', u'redhat-lsb', u'bison', u'flex', u'perl-ExtUtils-Embed', u'zlib-devel', u'crypto-utils', u'openssl-devel', u'pam-devel', u'libxml2-devel', u'libxslt-devel', u'tcl', u'tcl-devel', u'openssh-clients', u'bzip2', u'net-tools', u'wget', u'screen', u'ksh'])

TASK [postgresqldbserver : Add PostgreSQL operating system group] **************
ok: [192.168.22.171]
ok: [192.168.22.172]

TASK [postgresqldbserver : Add PostgreSQL operating system user] ***************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Download the PostgreSQL 9.5.3 sources] **************
ok: [192.168.22.172]
ok: [192.168.22.171]

TASK [postgresqldbserver : Copy PostgreSQL install script to targets] **********
changed: [192.168.22.171]
changed: [192.168.22.172]

TASK [postgresqldbserver : Compile and install PostgreSQL] *********************
changed: [192.168.22.172]
changed: [192.168.22.171]

TASK [postgresqldbserver : Copy the PostgreSQL cluster creation script to the targets] ***
ok: [192.168.22.171]
changed: [192.168.22.172]

TASK [postgresqldbserver : Create and start the PostgreSQL instance] ***********
changed: [192.168.22.172]
changed: [192.168.22.171]

PLAY RECAP *********************************************************************
192.168.22.171             : ok=9    changed=3    unreachable=0    failed=0   
192.168.22.172             : ok=9    changed=4    unreachable=0    failed=0   

… we should have a running PostgreSQL instance on both nodes, lets check:

[root@ansiblepg1 tmp]# ps -ef | grep postgres
postgres 17284     1  0 08:47 ?        00:00:00 /u01/app/postgres/product/95/db_3/bin/postgres -D /u02/pgdata/PG1
postgres 17288 17284  0 08:47 ?        00:00:00 postgres: checkpointer process   
postgres 17289 17284  0 08:47 ?        00:00:00 postgres: writer process   
postgres 17290 17284  0 08:47 ?        00:00:00 postgres: wal writer process   
postgres 17291 17284  0 08:47 ?        00:00:00 postgres: autovacuum launcher process   
postgres 17292 17284  0 08:47 ?        00:00:00 postgres: stats collector process   
root     17294 10223  0 08:47 pts/1    00:00:00 grep --color=auto postgres
[root@ansiblepg2 ~]# ps -ef | grep postgres
postgres 16951     1  0 08:47 ?        00:00:00 /u01/app/postgres/product/95/db_3/bin/postgres -D /u02/pgdata/PG1
postgres 16955 16951  0 08:47 ?        00:00:00 postgres: checkpointer process   
postgres 16956 16951  0 08:47 ?        00:00:00 postgres: writer process   
postgres 16957 16951  0 08:47 ?        00:00:00 postgres: wal writer process   
postgres 16958 16951  0 08:47 ?        00:00:00 postgres: autovacuum launcher process   
postgres 16959 16951  0 08:47 ?        00:00:00 postgres: stats collector process   
root     16985 16964  0 08:48 pts/0    00:00:00 grep --color=auto postgres

Isn’t that cool? Sure, there is much hard coding in here which needs to be extended by using variables. This is a topic for another post.

For your reference here is the complete playbook:

[ansible@ansiblecontrol ansible]$ cat /opt/ansible/roles/postgresqldbserver/tasks/main.yml 
---
- name: Install PostgreSQL dependencies
  yum: name={{item}} state=present
  with_items:
   - gcc
   - openldap-devel
   - python-devel
   - readline-devel
   - openssl-devel
   - redhat-lsb
   - bison
   - flex
   - perl-ExtUtils-Embed
   - zlib-devel
   - crypto-utils
   - openssl-devel
   - pam-devel
   - libxml2-devel
   - libxslt-devel
   - tcl
   - tcl-devel
   - openssh-clients
   - bzip2
   - net-tools
   - wget
   - screen
   - ksh

- name: Add PostgreSQL operating system group
  group: name=postgressomegroup state=present

- name: Add PostgreSQL operating system user
  user: name=postgres comment="PostgreSQL binaries owner" group=postgres

- name: Download the PostgreSQL 9.5.3 sources
  get_url: url=https://ftp.postgresql.org/pub/source/v9.5.3/postgresql-9.5.3.tar.bz2 dest=/var/tmp mode=0755

- name: Copy PostgreSQL install script to targets
  copy: src=install_pg953.sh dest=/var/tmp/install_pg953.sh owner=root group=root mode="u=rwx"

- name: Compile and install PostgreSQL
  shell: /var/tmp/install_pg953.sh >> /var/tmp/install_pg_log
  args:
    executable: /usr/bin/bash

- name: Copy the PostgreSQL cluster creation script to the targets
  copy: src=create_pg953_cluster.sh dest=/var/tmp/create_pg953_cluster.sh owner=root group=root mode="u=rwx"

- name: Create and start the PostgreSQL instance
  shell: /var/tmp/create_pg953_cluster.sh >> /var/tmp/create_pg_cluster.log
  args:
    executable: /usr/bin/bash
 

Cet article Getting started with Ansible – Creating the PostgreSQL instance est apparu en premier sur Blog dbi services.

Elasticsearch, Kibana, Logstash and Filebeat – Centralize all your database logs (and even more)

$
0
0

When it comes to centralizing logs of various sources (operating systems, databases, webservers, etc.) the ELK stack is becoming more and more popular in the open source world. ELK stands for Elasticsearch, Logstash and Kibana. Elasticsearch is based on Apache Lucene and the primary goal is to provide distributed search and analytic functions. Logstash is responsible to collect logs from a variety of systems and is able to forward these to Elasticsearch. Kibana is the data visualization platform on top of Elasticsearch. Nowadays the term ELK seems not be used anymore and people speak about the Elastic Stack. In this post I’ll look at how you can use these tools to centralize your PostgreSQL log file(s) into the Elastic Stack.

As usual my VMs are running CentOS although that should no be very important for the following (except for the yum commands). As Elasticsearch, Kibana and Logstash are all based on Java you’ll need to install java before starting. There are yum and apt repositories available but I’ll use the manual way for getting the pieces up and running.

The goal is to have one VM running Elasticsearch, Logstash and Kibana and another VM which will run the PostgreSQL instance and Filebeat. Lets start with the first one by installing java and setting up a dedicated user for running the stack:

[root@elk ~]# yum install -y java-1.8.0-openjdk
[root@elk ~]# groupadd elk
[root@elk ~]# useradd -g elk elk
[root@elk ~]# passwd elk
[root@elk ~]# mkdir -p /opt/elk
[root@elk ~]# chown elk:elk /opt/elk
[root@elk ~]# su - elk
[elk@elk ~]$ cd /opt/elk

The first of the products we’re going to install is Elasticsearch which is quite easy (we’ll not set up a distributed mode, only single node for the scope of this post). All we need to do is to download the tar file, extract and start:

[elk@elk ~]$ wget https://download.elastic.co/elasticsearch/release/org/elasticsearch/distribution/tar/elasticsearch/2.3.4/elasticsearch-2.3.4.tar.gz
[elk@elk elk]$ tar -axf elasticsearch-2.3.4.tar.gz
[elk@elk elk]$ ls -l
total 26908
drwxrwxr-x. 6 elk elk     4096 Jul 27 09:17 elasticsearch-2.3.4
-rw-rw-r--. 1 elk elk 27547169 Jul  7 15:05 elasticsearch-2.3.4.tar.gz
[elk@elk elk]$ cd elasticsearch-2.3.4
[elk@elk elasticsearch-2.3.4]$ bin/elasticsearch &

This will start up Elasticsearch and print some messages to the screen:

[2016-07-27 09:20:10,529][INFO ][node                     ] [Shinchuko Lotus] version[2.3.4], pid[10112], build[e455fd0/2016-06-30T11:24:31Z]
[2016-07-27 09:20:10,534][INFO ][node                     ] [Shinchuko Lotus] initializing ...
[2016-07-27 09:20:11,090][INFO ][plugins                  ] [Shinchuko Lotus] modules [reindex, lang-expression, lang-groovy], plugins [], sites []
[2016-07-27 09:20:11,114][INFO ][env                      ] [Shinchuko Lotus] using [1] data paths, mounts [[/ (rootfs)]], net usable_space [46.8gb], net total_space [48.4gb], spins? [unknown], types [rootfs]
[2016-07-27 09:20:11,115][INFO ][env                      ] [Shinchuko Lotus] heap size [1015.6mb], compressed ordinary object pointers [true]
[2016-07-27 09:20:11,115][WARN ][env                      ] [Shinchuko Lotus] max file descriptors [4096] for elasticsearch process likely too low, consider increasing to at least [65536]
[2016-07-27 09:20:12,637][INFO ][node                     ] [Shinchuko Lotus] initialized
[2016-07-27 09:20:12,637][INFO ][node                     ] [Shinchuko Lotus] starting ...
[2016-07-27 09:20:12,686][INFO ][transport                ] [Shinchuko Lotus] publish_address {127.0.0.1:9300}, bound_addresses {[::1]:9300}, {127.0.0.1:9300}
[2016-07-27 09:20:12,690][INFO ][discovery                ] [Shinchuko Lotus] elasticsearch/zc26XSa5SA-f_Kvm_jfthA
[2016-07-27 09:20:15,769][INFO ][cluster.service          ] [Shinchuko Lotus] new_master {Shinchuko Lotus}{zc26XSa5SA-f_Kvm_jfthA}{127.0.0.1}{127.0.0.1:9300}, reason: zen-disco-join(elected_as_master, [0] joins received)
[2016-07-27 09:20:15,800][INFO ][gateway                  ] [Shinchuko Lotus] recovered [0] indices into cluster_state
[2016-07-27 09:20:15,803][INFO ][http                     ] [Shinchuko Lotus] publish_address {127.0.0.1:9200}, bound_addresses {[::1]:9200}, {127.0.0.1:9200}
[2016-07-27 09:20:15,803][INFO ][node                     ] [Shinchuko Lotus] started

The default port is 9200 and you should now be able to talk to Elasticsearch:

[elk@elk elasticsearch-2.3.4]$ curl -X GET http://localhost:9200/
{
  "name" : "Shinchuko Lotus",
  "cluster_name" : "elasticsearch",
  "version" : {
    "number" : "2.3.4",
    "build_hash" : "e455fd0c13dceca8dbbdbb1665d068ae55dabe3f",
    "build_timestamp" : "2016-06-30T11:24:31Z",
    "build_snapshot" : false,
    "lucene_version" : "5.5.0"
  },
  "tagline" : "You Know, for Search"
}

Looks good. The next product we’ll need to install is Kibana. The setup itself is as easy as setting up Elasticsearch:

[elk@elk elasticsearch-2.3.4]$ cd /opt/elk/
[elk@elk elk]$ wget https://download.elastic.co/kibana/kibana/kibana-4.5.3-linux-x64.tar.gz
[elk@elk elk]$ tar -axf kibana-4.5.3-linux-x64.tar.gz
[elk@elk elk]$ cd kibana-4.5.3-linux-x64
[elk@elk kibana-4.5.3-linux-x64]$ grep elasticsearch.url config/kibana.yml 
elasticsearch.url: "http://localhost:9200"
[elk@elk kibana-4.5.3-linux-x64]$ bin/kibana &

Similar to Elasticsearch the startup messages are written to the screen:

  log   [09:27:30.208] [info][status][plugin:kibana] Status changed from uninitialized to green - Ready
  log   [09:27:30.237] [info][status][plugin:elasticsearch] Status changed from uninitialized to yellow - Waiting for Elasticsearch
  log   [09:27:30.239] [info][status][plugin:kbn_vislib_vis_types] Status changed from uninitialized to green - Ready
  log   [09:27:30.242] [info][status][plugin:markdown_vis] Status changed from uninitialized to green - Ready
  log   [09:27:30.253] [info][status][plugin:metric_vis] Status changed from uninitialized to green - Ready
  log   [09:27:30.257] [info][status][plugin:spyModes] Status changed from uninitialized to green - Ready
  log   [09:27:30.261] [info][status][plugin:statusPage] Status changed from uninitialized to green - Ready
  log   [09:27:30.263] [info][status][plugin:table_vis] Status changed from uninitialized to green - Ready
  log   [09:27:30.270] [info][listening] Server running at http://0.0.0.0:5601
  log   [09:27:35.320] [info][status][plugin:elasticsearch] Status changed from yellow to yellow - No existing Kibana index found
[2016-07-27 09:27:35,513][INFO ][cluster.metadata         ] [Shinchuko Lotus] [.kibana] creating index, cause [api], templates [], shards [1]/[1], mappings [config]
[2016-07-27 09:27:35,938][INFO ][cluster.routing.allocation] [Shinchuko Lotus] Cluster health status changed from [RED] to [YELLOW] (reason: [shards started [[.kibana][0]] ...]).
  log   [09:27:38.746] [info][status][plugin:elasticsearch] Status changed from yellow to green - Kibana index ready

To check if Kibana is really working point your browser to http://[hostname]:5601 (192.168.22.173 in my case):
kibana_01

The third product we’ll need is Logstash. It is almost the same procedure for getting it up and running:

[elk@elk kibana-4.5.3-linux-x64]$ cd /opt/elk/
[elk@elk elk]$ wget https://download.elastic.co/logstash/logstash/logstash-all-plugins-2.3.4.tar.gz
[elk@elk elk]$ tar -axf logstash-all-plugins-2.3.4.tar.gz
[elk@elk elk]$ cd logstash-2.3.4

To test if Logstash is running fine start a very simple pipeline:

[elk@elk logstash-2.3.4]$ bin/logstash -e 'input { stdin { } } output { stdout {} }'
Settings: Default pipeline workers: 1
Pipeline main started

Once this is up type something on the command line to check if Logstash is responding:

yipphea
2016-07-27T07:52:43.607Z elk yipphea

Looks good as well. For now we can stop Logstash again by “Control-c”:

^CSIGINT received. Shutting down the agent. {:level=>:warn}
stopping pipeline {:id=>"main"}
Received shutdown signal, but pipeline is still waiting for in-flight events
to be processed. Sending another ^C will force quit Logstash, but this may cause data loss. {:level=>:warn}

Pipeline main has been shutdown

Now we need to do some configuration to prepare Logtsash for receiving our PostgreSQL log file(s) through Filebeat. Filebeat will be responsible to forward the PostgreSQL log file(s) to Logstash.

[elk@elk logstash-2.3.4]$ pwd
/opt/elk/logstash-2.3.4
[elk@elk logstash-2.3.4]$ mkdir conf.d
[elk@elk logstash-2.3.4]$ cat conf.d/02-beats-input.conf
input {
  beats {
    port => 5044
    ssl => false
  }
}

What this is doing is telling Logstash that it shall create a new input of type beats and listen on port 5044 for incoming data. In addition to this input plugin Logstash will need an ouput plugin to know what it shall do with data coming in. As we want to send all the data to Elasticsearch we need to specify this:

[elk@elk logstash-2.3.4]$ cat conf.d/10-elasticsearch-output.conf
output {
  elasticsearch {
    hosts => ["localhost:9200"]
    sniffing => true
    manage_template => false
    index => "%{[@metadata][beat]}-%{+YYYY.MM.dd}"
    document_type => "%{[@metadata][type]}"
  }
}

Lets test if the configuration is fine (Logstash will read all configuration files in order):

[elk@elk logstash-2.3.4]$ bin/logstash --config /opt/elk/logstash-2.3.4/conf.d/ --configtest
Configuration OK

As all seems fine we can start Logstash with our new configuration:

[elk@elk logstash-2.3.4]$ bin/logstash --config /opt/elk/logstash-2.3.4/conf.d/ &
Settings: Default pipeline workers: 1
Pipeline main started

For being able to easily use the Filebeat index patterns in Kibana we’ll load the template dashboards provided by Elastic:

[elk@elk logstash-2.3.4]$ cd /opt/elk/
[elk@elk elk]$ wget http://download.elastic.co/beats/dashboards/beats-dashboards-1.2.3.zip
[elk@elk elk]$ unzip beats-dashboards-1.2.3.zip
[elk@elk elk]$ cd beats-dashboards-1.2.3
[elk@elk beats-dashboards-1.2.3]$ ./load.sh

Time to switch to the PostgreSQL VM to install Filebeat:

postgres@centos7:/u01/app/postgres/product/ [PG1] pwd
/u01/app/postgres/product
postgres@centos7:/u01/app/postgres/product/ [PG1] wget https://download.elastic.co/beats/filebeat/filebeat-1.2.3-x86_64.tar.gz
postgres@centos7:/u01/app/postgres/product/ [PG1] tar -axf filebeat-1.2.3-x86_64.tar.gz

Filebeat comes with an index template for Elasticsearch which we will now need to transfer to the host where Elasticsearch runs on for being able to load it:

postgres@centos7:/u01/app/postgres/product/filebeat-1.2.3-x86_64/ [PG1] ls *template*
filebeat.template.json
postgres@centos7:/u01/app/postgres/product/filebeat-1.2.3-x86_64/ [PG1] scp filebeat.template.json elk@192.168.22.173:/var/tmp/
elk@192.168.22.173's password: 
filebeat.template.json                                                      100%  814     0.8KB/s   00:00  

Locally on the host where Elasticsearch runs on we can now load the template into Elasticsearch:

[elk@elk elk]$ curl -XPUT 'http://localhost:9200/_template/filebeat' -d@/var/tmp/filebeat.template.json
{"acknowledged":true}
[elk@elk elk]$ 

Back to the PostgreSQL VM we need to configure Filebeat itself by adapting the filebeat.yml configuration file:

postgres@centos7:/u01/app/postgres/product/filebeat-1.2.3-x86_64/ [PG1] ls
filebeat  filebeat.template.json  filebeat.yml

There are only a few important points to configure. The first one is to tell Filebeat where to look for the PostgreSQL log files:

filebeat:
  # List of prospectors to fetch data.
  prospectors:
    # Each - is a prospector. Below are the prospector specific configurations
    -
      # Paths that should be crawled and fetched. Glob based paths.
      # To fetch all ".log" files from a specific level of subdirectories
      # /var/log/*/*.log can be used.
      # For each file found under this path, a harvester is started.
      # Make sure not file is defined twice as this can lead to unexpected behaviour.
      paths:
        - /u02/pgdata/PG1/pg_log/*.log

Afterwards make sure you disable/uncomment the Elasticsearch ouput plugin under the “output” section:

  ### Elasticsearch as output
  #elasticsearch:
    # Array of hosts to connect to.
    # Scheme and port can be left out and will be set to the default (http and 9200)
    # In case you specify and additional path, the scheme is required: http://localhost:9200/path
    # IPv6 addresses should always be defined as: https://[2001:db8::1]:9200
    #hosts: ["localhost:9200"]

Finally enable the Logstash output plugin in the same section (provide the host and port where you Logstash is running):

       ### Logstash as output
  logstash:
    # The Logstash hosts
    hosts: ["192.168.22.173:5044"]

The host and port specified here must match to what we specified in 02-beats-input.conf when we configured Logstash above. This should be sufficiant to startup Filebeat:

postgres@centos7:/u01/app/postgres/product/filebeat-1.2.3-x86_64/ [PG1] ./filebeat &

If everything is working fine we should now be able to ask Elasticsearch for our data from the PostgreSQL log file(s):

[elk@elk elk]$ curl -XGET 'http://localhost:9200/filebeat-*/_search?pretty'
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 5,
    "successful" : 5,
    "failed" : 0
  },
  "hits" : {
    "total" : 971,
    "max_score" : 1.0,
    "hits" : [ {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1F",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 06:57:34.030 CEST - 2 - 20831 -  - @ LOG:  MultiXact member wraparound protections are now enabled",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "type" : "log",
        "input_type" : "log",
        "fields" : null,
        "count" : 1,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "offset" : 112,
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1M",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 07:20:46.060 CEST - 2 - 20835 -  - @ LOG:  autovacuum launcher shutting down",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "fields" : null,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "offset" : 948,
        "type" : "log",
        "count" : 1,
        "input_type" : "log",
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1P",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 07:20:46.919 CEST - 5 - 20832 -  - @ LOG:  checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=0.000 s, sync=0.000 s, total=0.678 s; sync files=0, longest=0.000 s, average=0.000 s; distance=10908 kB, estimate=10908 kB",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "input_type" : "log",
        "count" : 1,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "type" : "log",
        "fields" : null,
        "offset" : 1198,
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1R",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:36:34.600 CEST - 1 - 2878 -  - @ LOG:  database system was shut down at 2016-05-15 07:20:46 CEST",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "offset" : 1565,
        "input_type" : "log",
        "count" : 1,
        "fields" : null,
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "type" : "log",
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1X",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:39:21.313 CEST - 3 - 3048 - [local] - postgres@postgres STATEMENT:  insert into t1 generate_series(1,1000000);",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "offset" : 2216,
        "type" : "log",
        "input_type" : "log",
        "count" : 1,
        "fields" : null,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1e",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:43:24.366 CEST - 3 - 3397 - [local] - postgres@postgres CONTEXT:  while updating tuple (0,1) in relation \"t1\"",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "offset" : 3165,
        "type" : "log",
        "input_type" : "log",
        "count" : 1,
        "fields" : null,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1l",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:43:46.776 CEST - 10 - 3397 - [local] - postgres@postgres CONTEXT:  while updating tuple (0,1) in relation \"t1\"",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "offset" : 4045,
        "type" : "log",
        "count" : 1,
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "input_type" : "log",
        "fields" : null,
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1r",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:45:39.837 CEST - 9 - 3048 - [local] - postgres@postgres ERROR:  type \"b\" does not exist at character 28",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "input_type" : "log",
        "count" : 1,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "offset" : 4799,
        "type" : "log",
        "fields" : null,
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1w",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:45:49.843 CEST - 14 - 3048 - [local] - postgres@postgres ERROR:  current transaction is aborted, commands ignored until end of transaction block",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "type" : "log",
        "fields" : null,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "offset" : 5400,
        "input_type" : "log",
        "count" : 1,
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    }, {
      "_index" : "filebeat-2016.07.27",
      "_type" : "log",
      "_id" : "AVYrey_1IfCoJOBMaP1x",
      "_score" : 1.0,
      "_source" : {
        "message" : "2016-05-15 09:45:49.843 CEST - 15 - 3048 - [local] - postgres@postgres STATEMENT:  alter table t1 add column b int;",
        "@version" : "1",
        "@timestamp" : "2016-07-27T08:31:44.940Z",
        "offset" : 5559,
        "count" : 1,
        "fields" : null,
        "beat" : {
          "hostname" : "centos7.local",
          "name" : "centos7.local"
        },
        "source" : "/u02/pgdata/PG1/pg_log/postgresql-Sun.log",
        "type" : "log",
        "input_type" : "log",
        "host" : "centos7.local",
        "tags" : [ "beats_input_codec_plain_applied" ]
      }
    } ]
  }
}

Quite a lot of information, so it is really working :) When we can ask Elasticsearch we should be able to use Kibana on the same data, too, shouldn’t we? Fire up your browser and point it to your Kibana URL (192.168.22.173:5601 in my case). You should see the “filebeat-*” index pattern in the upper left:

kibana_02

Select the “filebeat-*” index pattern:
kibana_03

To make this index the default one click on the green star:
kibana_04

Time to discover our data by using the “Discover” menu on the top:
kibana_05

The result of that should be that you can see all the PostgreSQL log messages on the screen:
kibana_06

Try to search something, e.g. “checkpoint complete”:
kibana_07

Not much happening on my instance so lets do some checkpoints:

postgres@centos7:/u01/app/postgres/product/filebeat-1.2.3-x86_64/ [PG1] sqh
psql (9.6beta1 dbi services build)
Type "help" for help.

(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.403 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.379 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.364 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.321 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.370 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.282 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.411 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 101.166 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.392 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.322 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.367 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.320 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.328 ms
(postgres@[local]:5432) [postgres] > checkpoint;
CHECKPOINT
Time: 100.285 ms

What is the picture now:
kibana_08

Isn’t that great? All the information near realtime, just by using a browser. In my case logs are coming from a single PostreSQL instance but logs could be coming from hundreds of instances. Logs could also be coming from webservers, application servers, operating system, network, … . All centralized in one place ready to analyze. Even better you could use Watcher to alert on changes on your data.

Ah, I can already hear it: But I need to see my performance metrics as well. No problem, there is the jdbc input plugin for Logstash. What can you do with that? Once configured you can query what ever you want from your database. Lets do a little demo.

As we downloaded Logstash with all plugins included already the jdbc input plugin is already there:

[elk@elk logstash-2.3.4]$ pwd
/opt/elk/logstash-2.3.4
[elk@elk logstash-2.3.4]$ find . -name *jdbc*
./vendor/bundle/jruby/1.9/gems/jdbc-sqlite3-3.8.11.2
./vendor/bundle/jruby/1.9/gems/jdbc-sqlite3-3.8.11.2/jdbc-sqlite3.gemspec
./vendor/bundle/jruby/1.9/gems/jdbc-sqlite3-3.8.11.2/lib/jdbc
./vendor/bundle/jruby/1.9/gems/jdbc-sqlite3-3.8.11.2/lib/sqlite-jdbc-3.8.11.2.jar
./vendor/bundle/jruby/1.9/gems/logstash-input-jdbc-3.1.0
./vendor/bundle/jruby/1.9/gems/logstash-input-jdbc-3.1.0/lib/logstash/inputs/jdbc.rb
./vendor/bundle/jruby/1.9/gems/logstash-input-jdbc-3.1.0/lib/logstash/plugin_mixins/jdbc.rb
./vendor/bundle/jruby/1.9/gems/logstash-input-jdbc-3.1.0/logstash-input-jdbc.gemspec
./vendor/bundle/jruby/1.9/gems/sequel-4.36.0/lib/sequel/adapters/jdbc
./vendor/bundle/jruby/1.9/gems/sequel-4.36.0/lib/sequel/adapters/jdbc/jdbcprogress.rb
./vendor/bundle/jruby/1.9/gems/sequel-4.36.0/lib/sequel/adapters/jdbc.rb
./vendor/bundle/jruby/1.9/specifications/jdbc-sqlite3-3.8.11.2.gemspec
./vendor/bundle/jruby/1.9/specifications/logstash-input-jdbc-3.1.0.gemspec

What you’ll need to provide in addtition is the jdbc driver for the database you want to connect to. In my case for PostgreSQL:

[elk@elk logstash-2.3.4]$ cd /opt/ elk/
[elk@elk elk]$ mkdir jdbc
[elk@elk elk]$ cd jdbc/
[elk@elk jdbc]$ wget https://jdbc.postgresql.org/download/postgresql-9.4.1209.jar
[elk@elk jdbc]$ ls
postgresql-9.4.1209.jar

All we need to do from here on is to configure another input and output plugin for Logstash:

[elk@elk conf.d]$ pwd
/opt/elk/logstash-2.3.4/conf.d
[elk@elk conf.d]$ cat 03-jdbc-postgres-input.conf
input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://192.168.22.99:5432/postgres"
        jdbc_user => "postgres"
        jdbc_password => "postgres"
        jdbc_validate_connection => true
        jdbc_driver_library => "/opt/elk/jdbc/postgresql-9.4.1209.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        statement => "SELECT * from pg_stat_activity"
    }
}
output {
    stdout { codec => json_lines }
}

Re-test if the configuration is fine:

[elk@elk logstash-2.3.4]$ bin/logstash --config /opt/elk/logstash-2.3.4/conf.d/ --configtest
Configuration OK

And then kill and restart Logstash:

[elk@elk logstash-2.3.4]$ bin/logstash --config /opt/elk/logstash-2.3.4/conf.d/

You should see data from pg_stat_activity right on the screen:

[elk@elk logstash-2.3.4]$ bin/logstash --config /opt/elk/logstash-2.3.4/conf.d/ 
Settings: Default pipeline workers: 1
Pipeline main started
{"datid":13322,"datname":"postgres","pid":3887,"usesysid":10,"usename":"postgres","application_name":"","client_addr":{"type":"inet","value":"192.168.22.173"},"client_hostname":null,"client_port":58092,"backend_start":"2016-07-27T13:15:25.421Z","xact_start":"2016-07-27T13:15:25.716Z","query_start":"2016-07-27T13:15:25.718Z","state_change":"2016-07-27T13:15:25.718Z","wait_event_type":null,"wait_event":null,"state":"active","backend_xid":null,"backend_xmin":{"type":"xid","value":"1984"},"query":"SELECT * from pg_stat_activity","@version":"1","@timestamp":"2016-07-27T13:15:26.712Z"}
{"message":"2016-07-27 15:15:25.422 CEST - 1 - 3887 - 192.168.22.173 - [unknown]@[unknown] LOG:  connection received: host=192.168.22.173 port=58092","@version":"1","@timestamp":"2016-07-27T13:15:32.054Z","source":"/u02/pgdata/PG1/pg_log/postgresql-Wed.log","offset":84795,"type":"log","input_type":"log","count":1,"beat":{"hostname":"centos7.local","name":"centos7.local"},"fields":null,"host":"centos7.local","tags":["beats_input_codec_plain_applied"]}
{"message":"2016-07-27 15:15:25.454 CEST - 2 - 3887 - 192.168.22.173 - postgres@postgres LOG:  connection authorized: user=postgres database=postgres","@version":"1","@timestamp":"2016-07-27T13:15:32.054Z","source":"/u02/pgdata/PG1/pg_log/postgresql-Wed.log","fields":null,"beat":{"hostname":"centos7.local","name":"centos7.local"},"count":1,"offset":84932,"type":"log","input_type":"log","host":"centos7.local","tags":["beats_input_codec_plain_applied"]}

As we want to have this data in Elasticsearch and analyze it with Kibana adjust the configuration to look like this and then restart Logstash:

input {
    jdbc {
        jdbc_connection_string => "jdbc:postgresql://192.168.22.99:5432/postgres"
        jdbc_user => "postgres"
        jdbc_password => "postgres"
        jdbc_validate_connection => true
        jdbc_driver_library => "/opt/elk/jdbc/postgresql-9.4.1209.jar"
        jdbc_driver_class => "org.postgresql.Driver"
        statement => "SELECT * from pg_stat_activity"
        schedule => "* * * * *"
    }
}
output {
    elasticsearch {
        index => "pg_stat_activity"
        document_type => "pg_stat_activity"
        document_id => "%{uid}"
        hosts => ["localhost:9200"]
    }
}

Once your restarted head over to Kibana and create a new index:
kibana_09

When you “Discover” you should see the data from pg_stat_activity:
kibana_10

Have fun with your data …

 

Cet article Elasticsearch, Kibana, Logstash and Filebeat – Centralize all your database logs (and even more) est apparu en premier sur Blog dbi services.

Viewing all 528 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>