Quantcast
Channel: Planet PostgreSQL
Viewing all 9683 articles
Browse latest View live

Michael Paquier: Postgres 12 highlight - New PGXS options for isolation and TAP tests

$
0
0

If you maintain some PostgreSQL extensions which rely on PGXS, a build infrastructure for PostgreSQL, the following commit added to Postgres 12 will be likely something interesting, because it adds new options to control more types of regression tests:

commit: d3c09b9b1307e022883801000ae36bcb5eef71e8
author: Michael Paquier <michael@paquier.xyz>
date: Mon, 3 Dec 2018 09:27:35 +0900
committer: Michael Paquier <michael@paquier.xyz>
date: Mon, 3 Dec 2018 09:27:35 +0900
Add PGXS options to control TAP and isolation tests, take two

The following options are added for extensions:
- TAP_TESTS, to allow an extention to run TAP tests which are the ones
present in t/*.pl.  A subset of tests can always be run with the
existing PROVE_TESTS for developers.
- ISOLATION, to define a list of isolation tests.
- ISOLATION_OPTS, to pass custom options to isolation_tester.

A couple of custom Makefile rules have been accumulated across the tree
to cover the lack of facility in PGXS for a couple of releases when
using those test suites, which are all now replaced with the new flags,
without reducing the test coverage.  Note that tests of contrib/bloom/
are not enabled yet, as those are proving unstable in the buildfarm.

Author: Michael Paquier
Reviewed-by: Adam Berlin, Álvaro Herrera, Tom Lane, Nikolay Shaplov,
Arthur Zakirov
Discussion: https://postgr.es/m/20180906014849.GG2726@paquier.xyz

This is similar rather to the existing REGRESS and REGRESS_OPTS which allow to respectively list a set of regression tests and pass down additional options to pg_regress (like a custom configuration file). When it comes to REGRESS, input files need to be listed in sql/ and expected output files are present in expected/, with items listed without a dedicated “.sql” suffix.

The new options ISOLATION and ISOLATION_OPTS added in PostgreSQL 12 are similar to REGRESS and REGRESS_OPTS, except that they can be used to define a set of tests to stress the behavior of concurrent sessions, for example for locking checks across commands, etc. PostgreSQL includes in its core tree the main set of isolation tests in src/test/isolation/, and has also a couple of modules with their own custom set:

  • contrib/test_decoding/
  • src/test/modules/snapshot_too_old/

To add such tests, a set of tests suffixed with “.spec” need to be added to a subdirectory of the module called specs/, matching with entries listed in ISOLATION without the suffix. Output files are listed in an subdirectory called expected/, suffixed with “.out” similarly to tests listed in REGRESS.

Another new option available is called TAP_TESTS, which allows a module to define if TAP tests need to be run. This is described extensively in the documentation as a facility which uses the Perl TAP tools. All the tests present in the subdirectory t/ and using “.pl” as suffix will be run. Note that a subset of tests can be enforced with the variable PROVE_FLAGS, which is useful for development purposes. Some modules use it in the core code:

  • contrib/oid2name/
  • contrib/vacuumlo/
  • src/test/modules/brin/
  • src/test/modules/commit_ts/
  • src/test/modules/test_pg_dump/

The main advantage of those switches is to avoid custom rules in one’s extension Makefile. Here is for example what has been used by many modules, including a couple of tools that I have developed and/or now maintain:

check:
    $(prove_check)

installcheck:
    $(prove_installcheck)

One of the main benefits is a huge cleanup of all the makefiles included in PostgreSQL core code which have accumulated custom rules across many releases, as well as better long-term maintenance of all in-core as well as out-of-core modules which depend on PGXS, so that is really a nice addition for the project.


Sebastian Insausti: How to Upgrade PostgreSQL10 to PostgreSQL11 with Zero Downtime

$
0
0

Historically, the hardest task when working with PostgreSQL has been dealing with the upgrades. The most intuitive upgrade way you can think of is to generate a replica in a new version and perform a failover of the application into it. With PostgreSQL, this was simply not possible in a native way. To accomplish upgrades you needed to think of other ways of upgrading, such as using pg_upgrade, dumping and restoring, or using some third party tools like Slony or Bucardo, all of them having their own caveats.

Why was this? Because of the way PostgreSQL implements replication.

PostgreSQL built-in streaming replication is what is called physical: it will replicate the changes on a byte-by-byte level, creating an identical copy of the database in another server. This method has a lot of limitations when thinking of an upgrade, as you simply cannot create a replica in a different server version or even in a different architecture.

So, here is where PostgreSQL 10 becomes a game changer. With these new versions 10 and 11, PostgreSQL implements built-in logical replication which, in contrast with physical replication, you can replicate between different major versions of PostgreSQL. This, of course, opens a new door for upgrading strategies.

In this blog, let's see how we can upgrade our PostgreSQL 10 to PostgreSQL 11 with zero downtime using logical replication. First of all, let's go through an introduction to logical replication.

What is logical replication?

Logical replication is a method of replicating data objects and their changes, based upon their replication identity (usually a primary key). It is based on a publish and subscribe mode, where one or more subscribers subscribe to one or more publications on a publisher node.

A publication is a set of changes generated from a table or a group of tables (also referred to as replication set). The node where a publication is defined is referred to as publisher. A subscription is the downstream side of logical replication. The node where a subscription is defined is referred to as the subscriber, and it defines the connection to another database and set of publications (one or more) to which it wants to subscribe. Subscribers pull data from the publications they subscribe to.

Logical replication is built with an architecture similar to physical streaming replication. It is implemented by "walsender" and "apply" processes. The walsender process starts logical decoding of the WAL and loads the standard logical decoding plugin. The plugin transforms the changes read from WAL to the logical replication protocol and filters the data according to the publication specification. The data is then continuously transferred using the streaming replication protocol to the apply worker, which maps the data to local tables and applies the individual changes as they are received, in a correct transactional order.

Logical Replication Diagram
Logical Replication Diagram

Logical replication starts by taking a snapshot of the data on the publisher database and copying that to the subscriber. The initial data in the existing subscribed tables are snapshotted and copied in a parallel instance of a special kind of apply process. This process will create its own temporary replication slot and copy the existing data. Once the existing data is copied, the worker enters synchronization mode, which ensures that the table is brought up to a synchronized state with the main apply process by streaming any changes that happened during the initial data copy using standard logical replication. Once the synchronization is done, the control of the replication of the table is given back to the main apply process where the replication continues as normal. The changes on the publisher are sent to the subscriber as they occur in real-time.

You can find more about logical replication in the following blogs:

How to upgrade PostgreSQL 10 to PostgreSQL 11 using logical replication

So, now that we know what this new feature is about, we can think about how we can use it to solve the upgrade issue.

We are going to configure logical replication between two different major versions of PostgreSQL (10 and 11), and of course, after you have this working, it is only a matter of performing an application failover into the database with the newer version.

We are going to perform the following steps to put logical replication to work:

  • Configure the publisher node
  • Configure the subscriber node
  • Create the subscriber user
  • Create a publication
  • Create the table structure in the subscriber
  • Create the subscription
  • Check the replication status

So let’s start.

On the publisher side, we are going to configure the following parameters in the postgresql.conf file:

  • listen_addresses: What IP address(es) to listen on. We'll use '*' for all.
  • wal_level: Determines how much information is written to the WAL. We are going to set it to logical.
  • max_replication_slots: Specifies the maximum number of replication slots that the server can support. It must be set to at least the number of subscriptions expected to connect, plus some reserve for table synchronization.
  • max_wal_senders: Specifies the maximum number of concurrent connections from standby servers or streaming base backup clients. It should be set to at least the same as max_replication_slots plus the number of physical replicas that are connected at the same time.

Keep in mind that some of these parameters required a restart of PostgreSQL service to apply.

The pg_hba.conf file also needs to be adjusted to allow replication. We need to allow the replication user to connect to the database.

So based on this, let’s configure our publisher (in this case our PostgreSQL 10 server) as follows:

  • postgresql.conf:
    listen_addresses = '*'
    wal_level = logical
    max_wal_senders = 8
    max_replication_slots = 4
  • pg_hba.conf:
    # TYPE  DATABASE        USER            ADDRESS                 METHOD
    host     all     rep     192.168.100.144/32     md5

We must change the user (in our example rep), which will be used for replication, and the IP address 192.168.100.144/32 for the IP that corresponds to our PostgreSQL 11.

On the subscriber side, it also requires the max_replication_slots to be set. In this case, it should be set to at least the number of subscriptions that will be added to the subscriber.

The other parameters that also need to be set here are:

  • max_logical_replication_workers: Specifies the maximum number of logical replication workers. This includes both apply workers and table synchronization workers. Logical replication workers are taken from the pool defined by max_worker_processes. It must be set to at least the number of subscriptions, again plus some reserve for the table synchronization.
  • max_worker_processes: Sets the maximum number of background processes that the system can support. It may need to be adjusted to accommodate for replication workers, at least max_logical_replication_workers + 1. This parameter requires a PostgreSQL restart.

So, we must configure our subscriber (in this case our PostgreSQL 11 server) as follows:

  • postgresql.conf:
    listen_addresses = '*'
    max_replication_slots = 4
    max_logical_replication_workers = 4
    max_worker_processes = 8

As this PostgreSQL 11 will be our new master soon, we should consider adding the wal_level and archive_mode parameters in this step, to avoid a new restart of the service later.

wal_level = logical
archive_mode = on

These parameters will be useful if we want to add a new replication slave or for using PITR backups.

In the publisher, we must create the user with which our subscriber will connect:

world=# CREATE ROLE rep WITH LOGIN PASSWORD '*****' REPLICATION; 
CREATE ROLE

The role used for the replication connection must have the REPLICATION attribute. Access for the role must be configured in pg_hba.conf and it must have the LOGIN attribute.

In order to be able to copy the initial data, the role used for the replication connection must have the SELECT privilege on a published table.

world=# GRANT SELECT ON ALL TABLES IN SCHEMA public to rep;
GRANT

We'll create pub1 publication in the publisher node, for all the tables:

world=# CREATE PUBLICATION pub1 FOR ALL TABLES;
CREATE PUBLICATION

The user that will create a publication must have the CREATE privilege in the database, but to create a publication that publishes all tables automatically, the user must be a superuser.

To confirm the publication created we are going to use the pg_publication catalog. This catalog contains information about all publications created in the database.

world=# SELECT * FROM pg_publication;
-[ RECORD 1 ]+------
pubname      | pub1
pubowner     | 16384
puballtables | t
pubinsert    | t
pubupdate    | t
pubdelete    | t

Column descriptions:

  • pubname: Name of the publication.
  • pubowner: Owner of the publication.
  • puballtables: If true, this publication automatically includes all tables in the database, including any that will be created in the future.
  • pubinsert: If true, INSERT operations are replicated for tables in the publication.
  • pubupdate: If true, UPDATE operations are replicated for tables in the publication.
  • pubdelete: If true, DELETE operations are replicated for tables in the publication.

As the schema is not replicated, we must take a backup in PostgreSQL 10 and restore it in our PostgreSQL 11. The backup will only be taken for the schema, since the information will be replicated in the initial transfer.

In PostgreSQL 10:

$ pg_dumpall -s > schema.sql

In PostgreSQL 11:

$ psql -d postgres -f schema.sql

Once we have our schema in PostgreSQL 11, we create the subscription, replacing the values of host, dbname, user, and password with those that correspond to our environment.

PostgreSQL 11:

world=# CREATE SUBSCRIPTION sub1 CONNECTION 'host=192.168.100.143 dbname=world user=rep password=*****' PUBLICATION pub1;
NOTICE:  created replication slot "sub1" on publisher
CREATE SUBSCRIPTION

The above will start the replication process, which synchronizes the initial table contents of the tables in the publication and then starts replicating incremental changes to those tables.

The user creating a subscription must be a superuser. The subscription apply process will run in the local database with the privileges of a superuser.

To verify the created subscription we can use then pg_stat_subscription catalog. This view will contain one row per subscription for the main worker (with null PID if the worker is not running), and additional rows for workers handling the initial data copy of the subscribed tables.

world=# SELECT * FROM pg_stat_subscription;
-[ RECORD 1 ]---------+------------------------------
subid                 | 16428
subname               | sub1
pid                   | 1111
relid                 |
received_lsn          | 0/172AF90
last_msg_send_time    | 2018-12-05 22:11:45.195963+00
last_msg_receipt_time | 2018-12-05 22:11:45.196065+00
latest_end_lsn        | 0/172AF90
latest_end_time       | 2018-12-05 22:11:45.195963+00

Column descriptions:

  • subid: OID of the subscription.
  • subname: Name of the subscription.
  • pid: Process ID of the subscription worker process.
  • relid: OID of the relation that the worker is synchronizing; null for the main apply worker.
  • received_lsn: Last write-ahead log location received, the initial value of this field being 0.
  • last_msg_send_time: Send time of last message received from origin WAL sender.
  • last_msg_receipt_time: Receipt time of last message received from origin WAL sender.
  • latest_end_lsn: Last write-ahead log location reported to origin WAL sender.
  • latest_end_time: Time of last write-ahead log location reported to origin WAL sender.

To verify the status of replication in the master we can use pg_stat_replication:

world=# SELECT * FROM pg_stat_replication;
-[ RECORD 1 ]----+------------------------------
pid              | 1178
usesysid         | 16427
usename          | rep
application_name | sub1
client_addr      | 192.168.100.144
client_hostname  |
client_port      | 58270
backend_start    | 2018-12-05 22:11:45.097539+00
backend_xmin     |
state            | streaming
sent_lsn         | 0/172AF90
write_lsn        | 0/172AF90
flush_lsn        | 0/172AF90
replay_lsn       | 0/172AF90
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 0
sync_state       | async

Column descriptions:

  • pid: Process ID of a WAL sender process.
  • usesysid: OID of the user logged into this WAL sender process.
  • usename: Name of the user logged into this WAL sender process.
  • application_name: Name of the application that is connected to this WAL sender.
  • client_addr: IP address of the client connected to this WAL sender. If this field is null, it indicates that the client is connected via a Unix socket on the server machine.
  • client_hostname: Hostname of the connected client, as reported by a reverse DNS lookup of client_addr. This field will only be non-null for IP connections, and only when log_hostname is enabled.
  • client_port: TCP port number that the client is using for communication with this WAL sender, or -1 if a Unix socket is used.
  • backend_start: Time when this process was started.
  • backend_xmin: This standby's xmin horizon reported by hot_standby_feedback.
  • state: Current WAL sender state. The possible values are: startup, catchup, streaming, backup and stopping.
  • sent_lsn: Last write-ahead log location sent on this connection.
  • write_lsn: Last write-ahead log location written to disk by this standby server.
  • flush_lsn: Last write-ahead log location flushed to disk by this standby server.
  • replay_lsn: Last write-ahead log location replayed into the database on this standby server.
  • write_lag: Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written it (but not yet flushed it or applied it).
  • flush_lag: Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written and flushed it (but not yet applied it).
  • replay_lag: Time elapsed between flushing recent WAL locally and receiving notification that this standby server has written, flushed and applied it.
  • sync_priority: Priority of this standby server for being chosen as the synchronous standby in a priority-based synchronous replication.
  • sync_state: Synchronous state of this standby server. The possible values are async, potential, sync, quorum.

To verify when the initial transfer is finished we can see the PostgreSQL log on the subscriber:

2018-12-05 22:11:45.096 UTC [1111] LOG:  logical replication apply worker for subscription "sub1" has started
2018-12-05 22:11:45.103 UTC [1112] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has started
2018-12-05 22:11:45.114 UTC [1113] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has started
2018-12-05 22:11:45.156 UTC [1112] LOG:  logical replication table synchronization worker for subscription "sub1", table "city" has finished
2018-12-05 22:11:45.162 UTC [1114] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has started
2018-12-05 22:11:45.168 UTC [1113] LOG:  logical replication table synchronization worker for subscription "sub1", table "country" has finished
2018-12-05 22:11:45.206 UTC [1114] LOG:  logical replication table synchronization worker for subscription "sub1", table "countrylanguage" has finished

Or checking the srsubstate variable on pg_subscription_rel catalog. This catalog contains the state for each replicated relation in each subscription.

world=# SELECT * FROM pg_subscription_rel;
-[ RECORD 1 ]---------
srsubid    | 16428
srrelid    | 16387
srsubstate | r
srsublsn   | 0/172AF20
-[ RECORD 2 ]---------
srsubid    | 16428
srrelid    | 16393
srsubstate | r
srsublsn   | 0/172AF58
-[ RECORD 3 ]---------
srsubid    | 16428
srrelid    | 16400
srsubstate | r
srsublsn   | 0/172AF90

Column descriptions:

  • srsubid: Reference to subscription.
  • srrelid: Reference to relation.
  • srsubstate: State code: i = initialize, d = data is being copied, s = synchronized, r = ready (normal replication).
  • srsublsn: End LSN for s and r states.

We can insert some test records in our PostgreSQL 10 and validate that we have them in our PostgreSQL 11:

PostgreSQL 10:

world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5001,'city1','USA','District1',10000);
INSERT 0 1
world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5002,'city2','ITA','District2',20000);
INSERT 0 1
world=# INSERT INTO city (id,name,countrycode,district,population) VALUES (5003,'city3','CHN','District3',30000);
INSERT 0 1

PostgreSQL 11:

world=# SELECT * FROM city WHERE id>5000;
  id  | name  | countrycode | district  | population
------+-------+-------------+-----------+------------
 5001 | city1 | USA         | District1 |      10000
 5002 | city2 | ITA         | District2 |      20000
 5003 | city3 | CHN         | District3 |      30000
(3 rows)

At this point, we have everything ready to point our application to our PostgreSQL 11.

For this, first of all, we need to confirm that we don't have replication lag.

On the master:

world=# SELECT  application_name,  pg_wal_lsn_diff(pg_current_wal_lsn(), replay_lsn) lag FROM pg_stat_replication;
-[ RECORD 1 ]----+-----
application_name | sub1
lag              | 0

And now, we only need to change our endpoint from our application or load balancer (if we have one) to the new PostgreSQL 11 server.

If we have a load balancer like HAProxy, we can configure it using the PostgreSQL 10 as active and the PostgreSQL 11 as backup, in this way:

HAProxy Status View
HAProxy Status View

So, if you just shutdown the master in PostgreSQL 10, the backup server, in this case in PostgreSQL 11, starts to receive the traffic in a transparent way for the user/application.

At the end of the migration, we can delete the subscription in our new master in PostgreSQL 11:

world=# DROP SUBSCRIPTION sub1;
NOTICE:  dropped replication slot "sub1" on publisher
DROP SUBSCRIPTION

And verify that it is removed correctly:

world=# SELECT * FROM pg_subscription_rel;
(0 rows)
world=# SELECT * FROM pg_stat_subscription;
(0 rows)
Download the Whitepaper Today
 
PostgreSQL Management & Automation with ClusterControl
Learn about what you need to know to deploy, monitor, manage and scale PostgreSQL

Limitations

Before using the logical replication, please keep in mind the following limitations:

  • The database schema and DDL commands are not replicated. The initial schema can be copied using pg_dump --schema-only.
  • Sequence data is not replicated. The data in serial or identity columns backed by sequences will be replicated as part of the table, but the sequence itself would still show the start value on the subscriber.
  • Replication of TRUNCATE commands is supported, but some care must be taken when truncating groups of tables connected by foreign keys. When replicating a truncate action, the subscriber will truncate the same group of tables that was truncated on the publisher, either explicitly specified or implicitly collected via CASCADE, minus tables that are not part of the subscription. This will work correctly if all affected tables are part of the same subscription. But if some tables to be truncated on the subscriber have foreign-key links to tables that are not part of the same (or any) subscription, then the application of the truncate action on the subscriber will fail.
  • Large objects are not replicated. There is no workaround for that, other than storing data in normal tables.
  • Replication is only possible from base tables to base tables. That is, the tables on the publication and on the subscription side must be normal tables, not views, materialized views, partition root tables, or foreign tables. In the case of partitions, you can replicate a partition hierarchy one-to-one, but you cannot currently replicate to a differently partitioned setup.

Conclusion

Keeping your PostgreSQL server up to date by performing regular upgrades has been a necessary but difficult task until PostgreSQL 10 version.

In this blog we made a brief introduction to logical replication, a PostgreSQL feature introduced natively in version 10, and we have shown you how it can help you accomplish this challenge with a zero downtime strategy.

Bruce Momjian: The Memory Resource Triad

$
0
0

There are three resources that affect query performance: CPU, memory, and storage. Allocating CPU and storage for optimal query performance is straightforward, or at least linear. For CPU, for each query you must decide the optimal number of CPUs to allocate for parallel query execution. Of course, only certain queries can benefit from parallelism, and the optimal number of CPU changes based on the other queries being executed. So, it isn't simple, but it is linear.

For storage, it is more of a binary decision — should the table or index be stored on fast media (SSDs) or slow media (magnetic disks), particularly fast random access. (Some NAS servers have even more finely-grained tiered storage.) It takes analysis to decide the optimal storage type for each table or index, but the Postgres statistic views can help to identify which objects would benefit.

Unfortunately, for memory, resource allocation is more complex. Rather than being a linear or binary problem, it is a multi-dimensional problem — let me explain. As stated above, for CPUs you have to decide how many CPUs to use, and for storage, what type. For memory, you have to decide how much memory to allocate to shared_buffers at database server start, and then decide how much memory to allocate to each query for sorting and hashing via work_mem. What memory that is not allocated gets used as kernel cache, which Postgres relies on for consistent performance (since all reads and writes go through that cache). So, to optimize memory allocation, you have to choose the best sizes for:

  1. shared buffers (fixed size at server start)
  2. work_mem (potentially optimized per query based on workload)
  3. kernel buffers (the remainder)

Continue Reading »

Lee Hampton: Evaluating High Availability Solutions for TimescaleDB + PostgreSQL

$
0
0

How we evaluated several third-party tools and ultimately selected Patroni as our preferred method.

If you are working with a database, you already know that high availability (HA) is a requirement for any reliable system. A proper HA setup eliminates the problem of a single point-of-failure by providing multiple places to get the same data, and an automated way of selecting a proper location with which to read and write data. PostgreSQL typically achieves HA by replicating the data on the primary database to one or more read-only replicas.

Streaming replication is the primary method of replication supported by TimescaleDB. It works by having the primary database server stream its write-ahead log (WAL) entries to its database replicas. Each replica then replays these log entries against its own database to reach a state consistent with the primary database.

Unfortunately, such streaming replication alone does not ensure that users don’t encounter some loss of uptime (“availability”) when a server crashes. If the primary node fails or becomes unreachable, there needs to be a method to promote one of the read replicas to become the new primary. And the faster that this failover occurs, the smaller the window of unavailability a user will see. One simple approach to such promotion is by manually performing it through a few PostgreSQL commands. On the other hand, automatic failover refers to a mechanism by which the system detects when a primary has failed, fully removes it from rotation (sometimes called fencing), promotes one read replica to primary status, and ensures the rest of the system is aware of the new state.

While PostgreSQL supports HA through its various replication modes, automatic failover is not something it supports out of the box. There are a number of third-party solutions that provide HA and automatic failover for PostgreSQL, many of which work with TimescaleDB because they also leverage streaming replication.

In this post, we will discuss how we evaluated third-party failover solutions and share deployment information about the one that best fits with our requirements and constraints. We will also provide a series of HA/failover scenarios that users may encounter and how to deal with these scenarios.

Requirements and constraints

When looking for a failover solution to adopt, we decided that it should meet the following requirements (in no particular order):

  • Does not require manual intervention for failover
  • Supports streaming replication (TimescaleDB is not currently compatible with logical replication, so methods relying on this or other custom protocols did not make the cut)
  • Supports different modes of replication (i.e. async vs synchronous commit)
  • Handles network partitions (commonly called “split brain,” where multiple instances think they are the primary databases and different clients may write to different servers, leading to inconsistencies)
  • Provides operational simplicity
  • Supports load balancing the read replicas
  • Plays nicely with cloud providers and containerized deployments
  • Uses a known/understood algorithm for establishing consensus (This is needed to ensure that the entire system agrees on which node the primary is. Many solutions will offload the consensus work to a system that already has a robust implementation of a known consensus algorithm. Patroni and Stolon, for example, use an etcd cluster, which implements the Raft consensus algorithm, to manage the system’s state.)
  • Supports the primary rejoining the cluster as a replica after being demoted and can become the primary again (failback)
  • Can be managed manually through some kind of interface (CLI, HTTP, GUI, etc.)
  • Has meaningful community adoption
  • Released under a permissive license

Evaluation of solutions

To begin, we evaluated several popular HA/failover solutions and their support for our requirements. Some solutions were closed source and not free, so they were not considered. Others were disqualified because they did not support streaming replication or different replication modes.

A handful of the requirements (community adoption, interface for management, no manual intervention for failover) were met by all options considered. We decided to rule out solutions that involve determining the master by configuring a floating/virtual IP, which would not work well in many modern cloud environments without jumping through some operational hoops. Additionally, we eliminated Corosync and Pacemaker since they were older products that required extra complexity and specialized knowledge.

We concluded that Stolon and Patroni both were good solutions. Their architectures are both easy to understand which is in no small part thanks to the fact that they offload all of the consensus heavy-lifting to etcd/consul. Adoption wise, they appear to be on equal footing, at least by the metric of Github stars, followers, and forks. There is also a good deal of documentation and sample configurations/scripts for both of them.

Ultimately we decided to choose Patroni because of its slightly simpler architecture and more modular approach to load balancing. Where Stolon requires you to use its own stolon-proxy nodes for load balancing, Patroni exposes health checks on the PostgreSQL nodes and lets you use Kubernetes, AWS ELB, HA Proxy, or another proxy solution to deal with load balancing. Where Stolon requires an additional layer of standalone sentinel and proxy services, Patroni is able to offer the same HA guarantees with “bots” on the PostgreSQL instances communicating with an etcd cluster.

Getting started with Patroni

The core architecture of Patroni looks like this:

Each PostgreSQL node has a Patroni bot deployed on it. The bots are capable both of managing the PostgreSQL database and updating the distributed consensus system (etcd in this case although Zookeeper, Consul, and the Kubernetes API, which is backed by etcd, are also perfectly fine options). Etcd must be deployed in an HA fashion that allows its individual nodes to reach a quorum about the state of the cluster. This requires a minimum deployment of 3 etcd nodes.

Leader election is handled by attempting to set an expiring key in etcd. The first PostgreSQL instance to set the etcd key via its bot becomes the primary. Etcd ensures against race conditions with a Raft-based consensus algorithm. When a bot receives acknowledgement that it has the key, it sets up the PostgreSQL instance as a primary. All other nodes will see that a primary has been elected and their bots will set their PostgreSQL instances up as replicas.

The primary key has a short TTLattached to it. The primary’s bot must continually health check its PostgreSQL instance and update the primary key. If this doesn’t happen because (a) the node loses connectivity, (b) the database fails, or (c) the bot dies, the key will expire. This will cause the primary to be fully removed from the system. When the replicas see that there is no primary key, each replica will attempt to become the primary unless it is obvious through exchanging information between bots that one of the primaries should be elected over the other. The bots will then either choose an obvious candidate for promotion or both race to be promoted to the primary.

You can find this flow illustrated below:

Common failover scenarios

There are a number of failover scenarios we made sure to test when fully evaluating failover functionality. Some of the key ones to keep in mind are:

  • The primary database crashes or is shut down
  • The server with the primary database crashes, is shut down, or is unreachable
  • A failed primary thinks it is a primary after failover
  • Replica databases crash or shut down
  • The Patroni bot on the primary goes down
  • The Patroni bot on the replica goes down
  • A replica is added to the cluster

Next steps

Above, we shared what we believe to be the best automatic failover solution for TimescaleDB users. While there are many third party solutions available, ultimately we went with Patroni because it combined robust and reliable failover with a simple architecture and easy-to-use interface.

If you are new to TimescaleDB and ready to get started, follow the installation instructions. If you have questions, we encourage you to join 1500+ member-strong Slack community. If you are looking for enterprise-grade support and assistance, please let us know.

Like this post? Interested in learning more? Follow us on Twitter or sign up for the community mailing list below!

https://medium.com/media/a6871827035ed1ae39a2e6e08e450fb1/href

Evaluating High Availability Solutions for TimescaleDB + PostgreSQL was originally published in Timescale on Medium, where people are continuing the conversation by highlighting and responding to this story.

Regina Obe: PostGIS 2.5.1 Bundle for Windows

$
0
0

PostGIS 2.5.1 was released on November 18th 2018 and I finished off packaging the PostGIS 2.5.1 windows builds and installers targeted for PostgreSQL EDB distribution this weekend and pushing them up to stackbuilder. This covers PostgreSQL 9.4-11 64-bit and PostgreSQL 95-10 (32bit).

Note that PostGIS 2.5 series will be the last of the PostGIS 2s. Goodbye PostGIS 2.* and start playing with the in-development version of PostGIS 3. Snapshot binaries for PostGIS 3.0 windows development are also available on the PostGIS windows download page. These should work for both BigSQL and EDB distributions.

Continue reading "PostGIS 2.5.1 Bundle for Windows"

Alexey Lesovsky: Keeping Postgres tidy with partitioning

$
0
0
If you are in doubt whether partitioning is a useful tool with this one example I'm hoping you won’t wonder any further.

Let’s assume we have some historical data, such as logs, jobs, actions, events, metrics or something else, that stored in the database.

=# select pg_size_pretty(pg_relation_size('history_log'));
 pg_size_pretty
----------------
 155 GB


=# select count(*) from history_log;
  count
------------
 2102342910


At some point, we decide to clean old events.

=# delete from history_log where updated_at < '2018-11-01';
DELETE 1885782465
Time: 327220.719 ms (12:05.221)


The query would take twelve minutes to complete. However, during this action there is a less noticeable process that takes place - query would generate certain amount of WAL that will then need to be transferred into all standbys.

Ok, let’s check how many rows there would be in the table.

=# select count(*) from history_log;
  count
-----------
 216560445


=# select 100 * 1885782465::bigint / 2102342910;
 ?column?
----------
       89

It seems we deleted something around of 89% of the table, but let’s check its size.

=# select pg_size_pretty(pg_relation_size('history_log'));
 pg_size_pretty
----------------
 155 GB


Huh, the size hasn’t been changed?!

The thing is, Postgres never performs real deletion. It just marks rows as removed. Later on, space occupied by these "removed" rows will be cleared by vacuum and the available space can again be used for new rows, however, this space still belongs to a table. In some rare circumstances, table can be partially truncated and the free space can be returned to the file system.

Using partitioning for storing historical data can work wonders. It would allow us to drop old data quickly, without overhead related to WAL generation, so it would immediately free up space.

Bruce Momjian: Allocating Work_mem

$
0
0

I have already discussed the complexities of allocating shared_buffers,work_mem, and the remainder as kernel cache. However, even if these could be optimally configured, work_mem (and its related setting maintenance_work_mem) are configured per query, and potentially can be allocated multiple times if multiple query nodes require it. So, even if you know the optimal amount of work_mem to allocate for the entire cluster, you still have to figure out how to allocate it among sessions.

This detailed email thread explores some possible ways to simplify this problem, but comes up with few answers. As stated, it is a hard problem, and to do it right is going to take a lot of work. Even DB2's solution to the problem was criticized, though it was our initial approach to solving the problem. With additional parallelism, configuring work_mem is getting even more complex for users, to say nothing of the complexity of allocating parallel workers itself.

This is eventually going to have to be addressed, and doing it in pieces is not going to be fruitful. It is going to need an entirely new subsystem, perhaps with dynamic characteristics unseen in any other Postgres modules.

Jonathan Katz: Get Started Running PostgreSQL on Kubernetes

$
0
0

Interested in running PostgreSQL natively on Kubernetes? Let's look at a few quick steps to get up and running with the open source Crunchy PostgreSQL Operator for Kubernetes on your choice of Kubernetes deployment.

The Crunchy PostgreSQL Operator (aka "pgo") provides a quickstart script to automate the deployment of the Crunchy PostgreSQL Operator to a number of popular Kubernetes environments, including Google Kubernetes Engine (GKE), OpenShift Container Platform (OCP) and Pivotal Container Service (PKS). You can download the quickstart script here:

The script will deploy the operator to a GKE Kubernetes cluster or an OpenShift Container Platform cluster. The script assumes you have a StorageClass defined for persistence.


Peter Bengtsson: How I performance test PostgreSQL locally on macOS

$
0
0

It's weird to do performance analysis of a database you run on your laptop. When testing some app, your local instance probably has 1/1000 the amount of realistic data compared to a production server. Or, you're running a bunch of end-to-end integration tests whose PostgreSQL performance doesn't make sense to measure.

Anyway, if you are doing some performance testing of an app that uses PostgreSQL one great tool to use is pghero. I use it for my side-projects and it gives me such nice insights into slow queries that I'm willing to live with the cost that it is to run it on a production database.

This is more of a brain dump of how I run it locally:

First, you need to edit your postgresql.conf. Even if you used Homebrew to install it, it's not clear where the right config file is. Start psql (on any database) and type this to find out which file is the one:

$ psql kintobench

kintobench=# show config_file;
               config_file
-----------------------------------------
 /usr/local/var/postgres/postgresql.conf
(1 row)

Now, open /usr/local/var/postgres/postgresql.conf and add the following lines:

# Peterbe: From Pghero's configuration help.
shared_preload_libraries = 'pg_stat_statements'
pg_stat_statements.track = all

Now, to restart the server use:

▶ brew services restart postgresql
Stopping `postgresql`... (might take a while)==> Successfully stopped `postgresql`(label: homebrew.mxcl.postgresql)==> Successfully started `postgresql`(label: homebrew.mxcl.postgresql)

The next thing you need is pghero itself and it's easy to run in docker. So to start, you need Docker for mac installed. You also need to know the database URL. Here's how I ran it:

docker run -ti -e DATABASE_URL=postgres://peterbe:@host.docker.internal:5432/kintobench -p 8080:8080 ankane/pghero

Duplicate indexes

Note the trick of peterbe:@host.docker.internal because I don't use a password but inside the Docker container it doesn't know my terminal username. And the host.docker.internal is so the Docker container can reach the PostgreSQL installed on the host.

Once that starts up you can go to http://localhost:8080 in a browser and see a listing of all the cumulatively slowest queries. There are other cool features in pghero too that you can immediately benefit from such as hints about unused/redundent database indices.

Hope it helps!

Laurenz Albe: Be prepared for prepared transactions

$
0
0

Prepared transactions are disabled in PostgreSQL by default, since the parameter max_prepared_transactions has the default value 0.

You don’t need prepared transactions in most cases. However, they can cause nasty problems, so I think that everybody who runs a PostgreSQL database should understand them.

To illustrate these problems, I’ll show you how to use prepared transactions to get a PostgreSQL into an inaccessible state.

 

What are prepared transactions?

Normally, a database transaction that spans multiple statements is ended with COMMIT or ROLLBACK. With prepared transactions, another step is added:

  1. BEGIN or START TRANSACTION: starts a transaction as usual.
  2. PREPARE TRANSACTION 'name': prepares the transaction for commit or rollback and assigns a name to it.
  3. { COMMIT | ROLLBACK } PREPARED 'name': commits or rolls back a previously prepared transaction.

 

The PREPARE TRANSACTION step performs all actions that may fail during COMMIT. That way, both COMMIT PREPARED and ROLLBACK PREPARED are guaranteed to succeed once a transaction is prepared. Moreover, PREPARE TRANSACTION persists the still open transaction, so that it will survive a crash or server restart.

Once a transaction is prepared, it is complete. Subsequent SQL statements belong to different transactions. You cannot do anything with a prepared transaction except COMMIT PREPARED and ROLLBACK PREPARED.

 

What is the use of prepared transactions?

Prepared transactions are used to implement “distributed transactions”.
Distributed transactions are transactions that affect more than one data source.
The protocol is as follows:

  1. Start a transaction on all data sources involved in the transaction.
  2. Modify data in the data sources. If there is a problem, ROLLBACK all involved transactions.
  3. Once you are done, PREPARE all involved transactions.
  4. If the PREPARE step fails in any of the transactions, issue ROLLBACK PREPARED everywhere.
  5. If the PREPARE step succeeds everywhere, COMMIT PREPARED all involved transactions.

 

This so-called “two-phase commit protocol” guarantees that the distributed transaction either succeeds or is rolled back everywhere, leaving the whole system consistent.

To make that works reliably, you need a “distributed transaction manager”.
That is software that keeps track of all distributed transactions, persisting their state to survive crashes and other interruptions.
That way it can complete all interrupted distributed transactions as soon as operation is resumed.

 

Problems caused by prepared transactions

Normally, no transaction should be in the prepared state for longer than a split second. But software bugs and other disruptions can cause a transaction to remain in the prepared state for a longer time. This causes the problems associated with long running transactions in general:

  • locks that are held for a long time, blocking other sessions and increasing the risk of a deadlock
  • VACUUM cannot clean up dead tuples created after the the start of the transaction

These problems are exacerbated by the fact that prepared transactions and their locks stay around even after the database server is restarted.

 

Implementation details

Preparing a transaction will write a WAL record, so the prepared transaction can be restored during crash recovery. This requires forcing the WAL to disk, just like a normal commit does.

During a checkpoint, the state of the prepared transaction is persisted in a file in the pg_twophase subdirectory of the data directory. The name of the file is the hexadecimal transaction ID.

On startup, all prepared transactions are restored from pg_twophase.

The file is deleted when the prepared transaction is committed or rolled back.

 

Getting rid of “orphaned” prepared transactions

You can examine all prepared transactions in the PostgreSQL database cluster using the view pg_prepared_xacts.

If a prepared transaction is “orphaned” because the transaction manager failed to close it, you will have to do that manually. Connect to the correct database and run COMMIT PREPARED or ROLLBACK PREPARED.

 

Locking up a database with prepared transactions

Warning: Don’t try this on your production database!

As a database superuser, run the following:

BEGIN;

LOCK pg_catalog.pg_authid;

PREPARE TRANSACTION 'locked';

Then disconnect from the database.

pg_authid, the table that contains the database users, is required to authenticate a database session. Since this table is locked by the prepared transaction, all future connection attempts will hang.

Restarting the database won’t help, because the prepared transaction will be retained.

Before you read on to the next part that contains the solution, let me invite you to try and get out of this dilemma yourself.

 

Enter Houdini!

Your first reaction will probably be the same as mine: Start PostgreSQL in single user mode. Alas, no luck:

$ pg_ctl stop
waiting for server to shut down.... done
server stopped
$ postgres --single postgres
LOG:  recovering prepared transaction 571 from shared memory
^C
FATAL:  canceling statement due to user request

Single user mode just hangs until I send it a SIGINT by pressing Ctrl+C, which shuts down the server.

But we can easily find a way to recover by reviewing the implementation details above:
571 in hexadecimal is 23b, so while PostgreSQL is shut down, we can remove the prepared transaction as follows:

$ rm $PGDATA/pg_twophase/0000023B

This will essentially roll back the transaction, and its effects will be undone when PostgreSQL is restarted.

The post Be prepared for prepared transactions appeared first on Cybertec.

Joshua Drake: PostgresConf 2019: Early bird tickets now available and CFP still open

$
0
0
We are pleased to announce that Early Bird tickets to Postgres Conference 2019 are now available. Whether you are seeking a world class big data and analytics learning opportunity from the Greenplum Summit, a deep dive from the Google Cloud Summit, Regulated Industry Information from the Regulated Industry track, or a dizzying amount of learning opportunities from over 100 breakout sessions, PostgresConf 2019 is the show not to miss! Oh, and did we mention there will be training options as well?

Register here:

https://postgresconf.org/conferences/2019

Call For Papers is still open! Submit your presentation at the above link.
 
 Postgres Conference 2019

PostgresConf would be impossible without the generous support of our sponsors including:
EnterpriseDB, Pivotal, Google, Microsoft and 2ndQuadrant.

Thanks for all of the support and we look forward to seeing you in March!

The Postgres Conference Organizer Team

Achilleas Mantzios: Using PostgreSQL Logical Replication to Maintain an Always Up-to-Date Read/Write TEST Server

$
0
0

In this blog entry we’ll talk about logical replication in PostgreSQL: its use cases, general information on the status of this technology, and a special use case in particular on how to setup a subscriber (replica) node of the primary server in order to function as the database server for the testing environment, and the challenges met.

Intro

Logical replication, officially introduced in PostgreSQL 10, is the latest replication technology offered by the PostgreSQL community. Logical replication is a continuation of the legacy of physical replication with which it shares a lot of ideas and code. Logical replication works like physical replication using the WAL to record logical changes independent from the version or specific architecture. In order to be able to provide logical replication to the core offering the PostgreSQL community has gone a long way.

Types of replication and History of PostgreSQL replication

The types of replication in databases can be classified as follows:

  • Physical (AKA binary) replication
    • Operating system level (vSphere replication)
    • File system level (DRBD)
    • Database level (WAL based)
  • Logical replication (Database level)
    • Trigger based (DBMirror, Slony)
    • Middleware (pgpool)
    • WAL based (pglogical, Logical Replication)

The roadmap that brings to today’s WAL based logical replication was:

  • 2001: DBMirror (trigger based)
  • 2004: Slony1 (trigger based), pgpool (middleware)
  • 2005: PITR (WAL based) introduced in PostgreSQL 8.0
  • 2006: Warm standby in PostgreSQL 8.2
  • 2010: Physical streaming replication, hot standby in PostgreSQL 9.0
  • 2011: Synchronous streaming replication in PostgreSQL 9.1
  • 2012: Cascading streaming replication in PostgreSQL 9.2
  • 2013: Background workers in PostgreSQL 9.3
  • 2014: Logical decoding API, replication slots. (The foundations for Logical Replication) in PostgreSQL 9.4
  • 2015: 2ndQuadrant introduces pglogical, the ancestor or Logical Replication
  • 2017: Logical Replication in core PostgreSQL 10!

As we can see lots of technologies collaborated to make Logical Replication a reality: WAL archiving, warm/hot standbys, physical WAL replication, background workers, logical decoding. Assuming the reader is familiar with most of the notions of physical replication, we’ll talk about the basic components of Logical Replication.

PostgreSQL Logical Replication basic concepts

Some terminology:

  • Publication: A set of changes from a set of tables defined in a specific database on a physical replication primary server. A Publication may handle all or some of: INSERT, DELETE, UPDATE, TRUNCATE.
  • Publisher node: The server where the publication resides.
  • Replica identity: A way to identify the row on the subscriber side for UPDATEs and DELETEs.
  • Subscription: A connection to a publisher node and one or more publications in it. A subscription uses a dedicated replication slot on the publisher for replication. Additional replication slots may be used for the initial synchronization step.
  • Subscriber node: The server where the subscription resides.

Logical replication follows a publish/subscribe model. One or more subscribers may subscribe to one or more publications on a publisher node. Subscribers may re-publish to allow for cascading replication. Logical replication of a table consists of two stages:

  • Taking a snapshot of the table on the publisher and copying it to the subscriber
  • Applying all changes (since the snapshot) in the same sequence

Logical replication is transactional and guarantees that the order of changes being applied to the subscriber remains the same as on the publisher. Logical replication gives much more freedom than physical (binary) replication, therefore can be used in more ways:

  • Single database or table specific replication (no need to replicate the whole cluster)
  • Setting triggers to the subscriber for a specific task (such as anonymizing, which is a pretty hot topic after GDPR came into force)
  • Having a subscriber node collect data from many publisher nodes, thus allowing for central analytical processing
  • Replication between different versions/architectures/platforms (zero downtime upgrades)
  • Using the subscriber node as the database server for a test/development environment. Why we want this, is because testing against real data is the most realistic kind of tests.

Caveats and Restrictions

There are certain things we must have in mind when using logical replication, some of them might influence some design decisions but others may lead to critical incidents.

Restrictions

  • Only DML operations are supported. No DDL. The schema has to be defined beforehand
  • Sequences are not replicated
  • Large Objects are not replicated
  • Only plain base tables are supported (materialized views, partition root tables, foreign tables are not supported)

Caveats

The basic issue that sooner or later we’ll have to face when using Logical Replication are conflicts on the subscriber. The subscriber is a normal read/write server which can act as primary in a physical replication setup, or even as publisher in a cascading logical replication setup. As long as writes on the subscribed tables are performed there might be conflicts. A conflict arises when replicated data violates a constraint on the table they are applied to. Usually, the operation that causes this is INSERT, DELETES or UPDATES which don't have any effect due to missing rows will not cause a conflict. When a conflict arises the replication stops. The logical background worker will be restarted in the specified interval (wal_retrieve_retry_interval), however, the replication will fail again until the cause of the conflict is resolved. This is a critical condition that must be dealt with immediately. Failing to do so will make the replication slot stuck at its current position, the publisher node will start accumulating WALs and inevitably the publisher node will run out of disk space. A conflict is the most common reason why replication might stop but any other erroneous condition will have the same effect: e.g. we added a new NOT NULL column on a subscribed table but forgot to define a default value, or added a column on a published table but forgot to define it on the subscribed table, or made a mistake on its type and the two types are not compatible. All those errors will stop the replication. There are two ways to resolve a conflict:

  1. Solve the actual problem
  2. Skip the failing transaction by calling pg_replication_origin_advance

Solution b. as also shown here can be dangerous and tricky as it is basically a trial and error process, and if one chooses the current LSN on the publisher he/she might easily end up with a broken replication system as there might be operations between the problematic LSN and the current LSN that we would want to keep. So the best way is to actually solve the problem on the subscriber side. E.g. if a UNIQUE KEY violation arises then we might update the data on the subscriber or just delete the row. In a production environment, all this must be automated or at least semi automated.

Setting up the publisher and subscriber nodes

For a general overview of the logical replication in practice please read this blog.

The relevant parameters for logical replication are:

  • Publisher side
    • wal_level >= “logical”
    • max_replication_slots >= #subscriptions + initial table synchronization
    • max_wal_senders >= max_replication_slots + other_physical_standbys
  • Subscriber side
    • max_replication_slots >= #subscriptions
    • max_logical_replication_workers >= #subscriptions + initial table synchronization
    • max_worker_processes >= max_logical_replication_workers + 1 + max_parallel_workers

We will focus on the special considerations that arise from our special purpose that we need logical replication to achieve: create a test database cluster for use by the testing dept. The publication may be defined either for all tables or table by table. I suggest the table by table approach as it gives us maximum flexibility. The general steps may be summarized as follows:

  • Perform a fresh initdb on the subscriber node
  • Dump the schema of the publisher cluster and copy to the subscriber node
  • Create the schema on the subscriber
  • Decide on which tables you need and which you don’t need.

Regarding the above bullet, there are two reasons on why you may not need a table to be replicated or setup for replication:

  • It is a dummy table with no importance (and maybe you should drop it from production as well)
  • is a table local to the production environment, which means that it makes perfect sense that the same table in the testing (subscriber) environment has its own data

All tables taking part in the logical replication must have a REPLICA IDENTITY. This is by default the PRIMARY KEY, and if not available a UNIQUE key can be defined. Next step to find the status of the tables with regards to REPLICA IDENTITY.

  • Find the tables with no obvious candidate for REPLICA IDENTITY
    select table_schema||'.'||table_name from information_schema.tables where table_type='BASE TABLE' AND table_schema||'.'||table_name NOT IN (select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type in ('PRIMARY KEY','UNIQUE')) AND table_schema NOT IN ('information_schema','pg_catalog') ;
  • Find the tables with no PRIMARY KEY but with a UNIQUE INDEX
    select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type = 'UNIQUE' EXCEPT select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type = 'PRIMARY KEY';
  • Go through the above lists and decide what to do with each table
  • Create the publication with the tables for which there exists a PK
    select 'CREATE PUBLICATION data_for_testdb_pub FOR TABLE ONLY ' || string_agg(qry.tblname,', ONLY ') FROM (select table_schema||'.'||quote_ident(table_name) as tblname from information_schema.tables where table_type='BASE TABLE' AND table_schema||'.'||table_name IN (select table_schema||'.'||table_name from information_schema.table_constraints WHERE constraint_type in ('PRIMARY KEY')) AND table_schema NOT IN( 'information_schema','pg_catalog')  ORDER BY 1) as qry;
    \gexec
  • Then create the subscription on the subscriber node
    create subscription data_for_testdb_pub CONNECTION 'dbname=yourdb host=yourdbhost user=repmgr' PUBLICATION data_for_testdb_pub ;
    The above will copy the data as well.
  • Add tables that you want which have a UNIQUE index
    Run both in publisher and subscriber nodes, e.g.:
    ALTER TABLE someschema.yourtable REPLICA IDENTITY USING INDEX yourindex_ukey;
    On the publisher:
    ALTER PUBLICATION data_for_testdb_pub ADD TABLE ONLY someschema.yourtable;
    On the subscriber:
    ALTER SUBSCRIPTION data_for_testdb_pub REFRESH PUBLICATION WITH ( COPY_DATA );
  • At this point (synchronization) you should always have an eye on the PostgreSQL log on the subscriber node. You don’t want any errors or anything (timeout) which prohibit the continuation of logical replication. SOLVE ANY ERROR IMMEDIATELY, or the publisher will keep accumulating WAL files in pg_wal and eventually run out of space. So you have to deal with
    • All ERRORs or any message regarding the logical worker which results in exiting
    • Also take care of
      • wal_receiver_timeout
      • wal_sender_timeout

After solving all problems you should have your subscriber node running happily. So the next question is how to use this as a test database server. You will have to deal with those problems/issues:

  1. Anonymization
  2. Primary keys and Unique keys which are based on sequences violations
  3. A general set of good practices
  4. Monitoring

Anonymization

Regarding anonymization of personal data which is enforced by GDPR in EU, you should write some ALWAYS triggers that blank out all fields regarding addresses, bank accounts, marital status, phone numbers, emails, etc. You should consult your security officer in your company about what to keep and what to blank out. The triggers should be defined as ALWAYS since the logical worker runs the statements as REPLICA.

Primary Keys with Sequences

Regarding sequences, clearly there is gonna be a problem with those keys unless dealt with before any test is started. Consider this case:

  • On Friday afternoon you make some tests on the subscriber database inserting a new row to some table. This will have as an ID the next value generated by the sequence.
  • You go home for the weekend.
  • Some production user enters a row in the same table on the publisher database.
  • The row will be replicated based on the REPLICA IDENTITY to the subscriber node but will fail due to PK violation ERROR. The logical background worker will exit and retry. But will keep failing as long as the problem persists.
  • The replication will stuck. The replication slot will start accumulating WALs.
  • The publisher runs out of disk space.
  • On the weekend you get an email that your Primary node has PANIC’ed!

So, in order to solve the sequence problem you may take the following approach:

select 'SELECT setval(''' || seqrelid::regclass||''','||CASE WHEN seqincrement <0 THEN -214748364 ELSE 214748364 END||');' from pg_sequence where seqtypid=20;
\gexec

What the above does is to set sequences to a large enough value so that they never overlap for a fairly large window in the future, allowing you to have a problem-free test server.

A set of Good Practices

You should really tell your programmers to make their tests non persistent. So any test after it completes should leave the database in the same state as it was prior to the test. With sequence-based IDs insertions this is not an issue, we saw earlier a solution. But with non-sequence (e.g. compound) UNIQUE keys that might be a problem. So it’s best to delete those test data before some production row with the same value hits the subscribed table.

Here we should also add dealing with schema changes. All schema changes must be done also on the subscriber in order not to break replicated DML traffic.

Download the Whitepaper Today
 
PostgreSQL Management & Automation with ClusterControl
Learn about what you need to know to deploy, monitor, manage and scale PostgreSQL

Monitoring

You really should invest in a good monitoring solution. You should monitor for ...

At the subscriber:

  • ALL messages in subscriber’s log that relevant to logical worker exit. Installing a tool as tail_n_mail can really help with this. A configuration known to work:
    INCLUDE: ERROR:  .*publisher.*
    INCLUDE: ERROR:  .*exited with exit.*
    INCLUDE: LOG:  .*exited with exit.*
    INCLUDE: FATAL:  
    INCLUDE: PANIC:
    Once we get an alert coming from tail_n_mail we should immediately solve the problem.
  • pg_stat_subscription. Pid should be not null. Also the lag should be small.

At the publisher:

  • pg_stat_replication. This should have as many rows as they are supposed to be: One for each connected streaming replication standby (subscriber nodes and other physical standbys included).
  • pg_replication_slots for the subscriber slot. This should be active.

Generally, it takes some time till you have your ideal test database server running without problems, but once you have solved them all, your programmers will thank you for having it!

Luca Ferrari: PostgreSQL 11 Server Side Programming - Now Available!

$
0
0

A quick start guide on implementing and deploying code to PostgreSQL.

PostgreSQL 11 Server Side Programming - Now Available!

Near the end of November, Packt published the book PostgreSQL 11 Server Side Programming Quick Start Guide, authored by me.

PostgreSQL-11-ServerSideProgramming-cover-image



*This post has the only aim of describing the book contents and the reason behind choices related to it.**

Following a consolidated tradition, Packt is producing more and more books on PostgreSQL and related technologies, and this is the first one that covers aspects about the freshly released PostgreSQL 11 version.

Nevertheless, this does not mean that the book is only for PostgreSQL 11 users and administrators: it covers topics, concepts and provide examples that can be use as-is or ported to older versions of PostgreSQL, as well as probably to newer ones. In fact, while the book code examples have been tested against a PostgreSQL 11 cluster, only the examples related to the new object PROCEDURE, introduced by PostgreSQL 11, are strongly tied to such a version.

This book is a Quick Start Guide, and therefore it has a very practical approach to a limited scope, and only that. Therefore the book assumes you are able to install, manage and run a PostgreSQL 11 cluster, that you know how to connect and how to handle basic SQL statements. A basic knowledge in general programming is also required.

The book consists of 10 chapters, each focusing on a particular aspect of developing and deploying code within a PostgreSQL cluster. The main programming language used in the book is PL/pgSQL, the default procedural language for PostgreSQL; however several examples are...

Bruce Momjian: Optimizer Hints

$
0
0

You might know that Postgres has optimizer hints listed as a feature we do not want to implement. I have covered this topic in the past.

This presentation from Tatsuro Yamada covers the trade-offs of optimizer hints in more detail than I have ever seen before. Starting on slide 29, Yamada-san explains the number-one reason to use optimizer hints — as a short-term fix for inefficient query plans. He uses pg_hint_plan (produced by NTT) to fix inefficient plans in his use case. He then goes on to consider possible non-hint solutions to inefficient plans, such as recording data distributions found during execution for use in the optimization of later queries.

Most interesting to me was his reproduction of the optimizer hints discussion on the Postgres wiki, including his analysis of how pg_hint_plan fits that criteria. There are certainly environments where optimizer hints are helpful, and it seems Yamada-san has found one. The reason the community does not plan to support hints is that it is considered likely that optimizer hints would cause more problems for users than they solve. While Postgres has some crude manual optimizer controls, it would certainly be good if Postgres could come up with additional solutions that further minimize the occurrence of significantly inefficient plans.

Nickolay Ihalainen: PostgreSQL Streaming Physical Replication With Slots

$
0
0
postgres replication using slots

PostgreSQLPostgreSQL streaming physical replication with slots simplifies setup and maintenance procedures. Usually, you should estimate disk usage for the Write Ahead Log (WAL) and provide appropriate limitation to the number of segments and setup of the WAL archive procedure. In this article, you will see how to use replication with slots and understand what problems it could solve.

Introduction

PostgreSQL physical replication is based on WAL. Th Write Ahead Log contains all database changes, saved in 16MB segment files. Normally postgres tries to keep segments between checkpoints. So with default settings, just 1GB of WAL segment files is available.

Replication requires all WAL files created after backup and up until the current time. Previously, it was necessary to keep a huge archive directory (usually mounted by NFS to all slave servers). The slots feature introduced in 9.4 allows Postgres to track the latest segment downloaded by a slave server. Now, PostgreSQL can keep all segments on disk, even without archiving, if a slave is seriously behind its master due to downtime or networking issues. The drawback: the disk space could be consumed infinitely in the case of configuration error. Before continuing, if you need a better understanding of physical replication and streaming replication, I recommend you read “Streaming Replication with PostgreSQL“.

Create a sandbox with two PostgreSQL servers

To setup replication, you need at least two PostgreSQL servers. I’m using pgcli (pgc) to setup both servers on the same host. It’s easy to install on Linux, Windows, and OS X, and provides the ability to download and run any version of PostgreSQL on your staging server or even on your laptop.

python -c "$(curl -fsSL https://s3.amazonaws.com/pgcentral/install.py)"
mv bigsql master
cp -r master slave
$ cd master
master$ ./pgc install pg10
master$ ./pgc start pg10
$ cd ../slave
slave$ ./pgc install pg10
slave$ ./pgc start pg10

First of all you should allow the replication user to connect:

master$ echo "host replication replicator 127.0.0.1/32 md5" >> ./data/pg10/pg_hba.conf

If you are running master and slave on different servers, please replace 127.0.0.1 with the slave’s address.

Next pgc creates a shell environment file with PATH and all the other variables required for PostgreSQL:

master$ source ./pg10/pg10.env

Allow connections from the remote host, and create a replication user and slot on master:

master$ psql
postgres=# CREATE USER replicator WITH REPLICATION ENCRYPTED PASSWORD 'replicator';
CREATE ROLE
postgres=# ALTER SYSTEM SET listen_addresses TO '*';
ALTER SYSTEM
postgres=# SELECT pg_create_physical_replication_slot('slot1');
pg_create_physical_replication_slot
-------------------------------------
(slot1,)

To apply system variables changes and hba.conf, restart the Postgres server:

master$ ./pgc stop ; ./pgc start
pg10 stopping
pg10 starting on port 5432

Test table

Create a table with lots of padding on the master:

master$ psql psql (10.6) Type "help" for help.
postgres=# CREATE TABLE t(id INT, pad CHAR(200));
postgres=# CREATE INDEX t_id ON t (id);
postgres=# INSERT INTO t SELECT generate_series(1,1000000) AS id, md5((random()*1000000)::text) AS pad;

Filling WAL with random data

To see the benefits of slots, we should fill the WAL with some data by running transactions. Repeat the update statement below to generate a huge amount of WAL data:

UPDATE t SET pad = md5((random()*1000000)::text);

Checking the current WAL size

You can check total size for all WAL segments from the shell or from psql:

master$ du -sh data/pg10/pg_wal
17M data/pg10/pg_wal
master$ source ./pg10/pg10.env
master$ psql
postgres=# \! du -sh data/pg10/pg_wal
17M data/pg10/pg_wal

Check maximum WAL size without slots activated

Before replication configuration, we can fill the WAL with random data and find that after 1.1G, the data/pg10/pg_wal directory size does not increase regardless of the number of update queries.

postgres=# UPDATE t SET pad = md5((random()*1000000)::text); -- repeat 4 times
postgres=# \! du -sh data/pg10/pg_wal
1.1G data/pg10/pg_wal
postgres=# UPDATE t SET pad = md5((random()*1000000)::text);
postgres=# \! du -sh data/pg10/pg_wal
1.1G data/pg10/pg_wal

Backup master from the slave server

Next, let’s make a backup for our slot1:

slave$ source ./pg10/pg10.env
slave$ ./pgc stop pg10
slave$ rm -rf data/pg10/*
# If you are running master and slave on different servers, replace 127.0.0.1 with master's IP address.
slave$ PGPASSWORD=replicator pg_basebackup -S slot1 -h 127.0.0.1 -U replicator -p 5432 -D $PGDATA -Fp -P -Xs -Rv

Unfortunately pg_basebackup hangs with: initiating base backup, waiting for checkpoint to complete.
We can wait for the next checkpoint, or force the checkpoint on the master. Checkpoint happens every checkpoint_timeout seconds, and is set to five minutes by default.

Forcing checkpoint on master:

master$ psql
postgres=# CHECKPOINT;

The backup continues on the slave side:

pg_basebackup: checkpoint completed
pg_basebackup: write-ahead log start point: 0/92000148 on timeline 1
pg_basebackup: starting background WAL receiver
1073986/1073986 kB (100%), 1/1 tablespace
pg_basebackup: write-ahead log end point: 0/927FDDE8
pg_basebackup: waiting for background process to finish streaming ...
pg_basebackup: base backup completed

The backup copies settings from the master, including its TCP port value. I’m running both master and slave on the same host, so I should change the port in the slave .conf file:

slave$ vim data/pg10/postgresql.conf
# old value port = 5432
port = 5433

Now we can return to the master and run some queries:

slave$ cd ../master
master$ source pg10/pg10.env
master$ psql
postgres=# UPDATE t SET pad = md5((random()*1000000)::text);
UPDATE t SET pad = md5((random()*1000000)::text);

By running these queries, the WAL size is now 1.4G, and it’s bigger than 1.1G! Repeat this update query three times and the WAL grows to 2.8GB:

master$ du -sh data/pg10/pg_wal
2.8G data/pg10/pg_wal

Certainly, the WAL could grow infinitely until whole disk space is consumed.
How do we find out the reason for this?

postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn    | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
1/2A400630  | slot1     |  0/92000000 | 2.38

We have one slot behind the master of 2.38GB.

Let’s repeat the update and check again. The gap has increased:

postgres=# postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn    | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
1/8D400238  |     slot1 | 0/92000000  | 3.93

Wait, though: we have already used slot1 for backup! Let’s start the slave:

master$ cd ../slave
slave$ ./pgc start pg10

Replication started without any additional change to recovery.conf:

slave$ cat data/pg10/recovery.conf
standby_mode = 'on'
primary_conninfo = 'user=replicator password=replicator passfile=''/home/pguser/.pgpass'' host=127.0.0.1 port=5432 sslmode=prefer sslcompression=1 krbsrvname=postgres target_session_attrs=any'
primary_slot_name = 'slot1'

pg_basebackup -R option instructs backup to write to the recovery.conf file with all required options, including primary_slot_name.

WAL size, all slots connected

The gap reduced several seconds after the slave started:

postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn    | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
 1/8D400238 |     slot1 |  0/9A000000 | 3.80

And a few minutes later:

postgres=# SELECT redo_lsn, slot_name,restart_lsn,
round((redo_lsn-restart_lsn) / 1024 / 1024 / 1024, 2) AS GB_behind
FROM pg_control_checkpoint(), pg_replication_slots;
redo_lsn    | slot_name | restart_lsn | gb_behind
------------+-----------+-------------+-----------
 1/9E5DECE0 |     slot1 |  1/9EB17250 | -0.01
postgres=# \!du -sh data/pg10/pg_wal
1.3G data/pg10/pg_wal

Slave server maintenance

Let’s simulate slave server maintenance with ./pgc stop pg10 executed on the slave. We’ll push some data onto the master again (execute the UPDATE query 4 times).

Now, “slot1” is again 2.36GB behind.

Removing unused slots

By now, you might realize that a problematic slot is not in use. In such cases, you can drop it to allow retention for segments:

master$ psql
postgres=# SELECT pg_drop_replication_slot('slot1');

Finally the disk space is released:

master$ du -sh data/pg10/pg_wal
1.1G data/pg10/pg_wal

Important system variables

  • archive_mode is not required for streaming replication with slots.
  • wal_level – is replica by default
  • max_wal_senders – set to 10 by default, a minimum of three for one slave, plus two for each additional slave
  • wal_keep_segments – 32 by default, not important because PostgreSQL will keep all segments required by slot
  • archive_command – not important for streaming replication with slots
  • listen_addresses – the only option that it’s necessary to change, to allow remote slaves to connect
  • hot_standby – set to on by default, important to enable reads on slave
  • max_replication_slots – 10 by default https://www.postgresql.org/docs/10/static/runtime-config-replication.html

Summary

  • Physical replication setup is really easy with slots. By default in pg10, all settings are already prepared for replication setup.
  • Be careful with orphaned slots. PostgreSQL will not remove WAL segments for inactive slots with initialized restart_lsn.
  • Check pg_replication_slots restart_lsn value and compare it with current redo_lsn.
  • Avoid long downtime for slave servers with slots configured.
  • Please use meaningful names for slots, as that will simplify debug.

References


Bruce Momjian: Micro-Optimizations

$
0
0

This email thread discusses the tradeoffs of adding optimization improvements that affect only a small percentage of queries, i.e., micro-optimizations. The big sticking point is that we don't know if the time required to check for these optimizations is worth it. For short-running queries, it probably isn't, but for long-running queries, it probably is. The problem is that we don't know the final cost of the query until the end the optimization stage — this makes it impossible to decide if checks for micro-optimizations are worthwhile during optimization.

During the email discussion, optimizing X = X clauses was considered to be a win for all queries, so was applied. Optimization to convert OR queries to use UNION is still being considered. Figuring out a way to estimate the cost before optimization starts was recently discussed.

Will Leinweber: \watch ing Star Wars in Postgres

$
0
0

I recently had the honor of speaking at the last Keep Ruby Weird. A good part of the talk dealt with Postgres and since Citus is a Postgres company I figured sharing those parts on the blog would be a good idea. If you’d like to see it in talk form, or you’d also like to know how to watch movies rendered as emojis in your terminal, I encourge you to watch the talk.

So, obviously we want to watch Star Wars in psql. The first step though is getting all of the frames into a format that makes sense. http://asciimation.co.nz by Simon Jansen is an ASCII version of Star Wars, and is perfect for our needs. Simon hand drew all of the frames and it looks like this:

                                        ====
          Help me,                      o o~~
      Obi-Wan Kenobi!                  _\O /_
                           ___        / \ /  \
                          /() \      //| |  |\\
                        _|_____|_   // | |  |//
            ,@         | | === | | //  | |  //
            /=-        |_|  O  |_|('   |===(|
            ||          ||  O  ||      | || |
            ||          ||__*__||      (_)(_)
          --~~---      |~ \___/ ~|     |_||_|
          |     |      /=\ /=\ /=\     |_||_|
 _________|_____|______[_]_[_]_[_]____/__][__\______________________

We can get all of the data using curl as long as we get it using gzip, and then we can extract the frames out of the single, very long javacript line that starts with var film =. The format is a number representing how many times this particular frame should be repeated and is followed by fourteen lines separated by new line characters.

raw = File.readlines("site.html")
  .find {|line| line.start_with? "var film"}
  .encode('UTF-8','binary',invalid: :replace,undef: :replace,replace: '')
  .gsub(%q{\'},"'")[12..-16]
  .split('\n')
  .each_slice(14)

Once we have that we can store it in a postgres table

CREATE TABLE film (
  i     serial PRIMARY KEY,
  count int    NOT NULL,
  frame text   NOT NULL
);
require 'sequel'
db = Sequel.connect("postgres:///")

raw.each do |data|
  count, *frame = data
  db[:film] << {count: count.to_i, frame: frame.join("\n")}
end

To watch this, we’re going to want some way that will show the frame then sleep for the appropriate amount of time. Postgres functions are perfect for this. This one will actually sleep for the duration requried for the previous frame, then display the current frame.

CREATE OR REPLACE FUNCTION go(speed numeric, ctr bigint)
RETURNS text AS $$
  begin
    PERFORM pg_sleep(count*speed) FROM film WHERE i=ctr-1; -- 😴
    RETURN (SELECT frame FROM film WHERE i=ctr);           -- 👀
  end
$$ LANGUAGE plpgsql;

We’re almost have all the pieces together, but we need a way to keep track of the current frame. If you create a table with an auto-incrementing column, behind the scenes, Postgres creates a sequence to keep track of the current value. You can create unattached sequences however, and control where they start.

CREATE SEQUENCE ctr;
SELECT nextval('ctr'); -- 1
SELECT nextval('ctr'); -- 2
SELECT nextval('ctr'); -- 3

ALTER SEQUENCE ctr RESTART 200;
SELECT nextval('ctr'); -- 200
SELECT nextval('ctr'); -- 201

And with that, SELECT go(0.01, nextval('ctr')); can be run over and over again to watch Star Wars inside psql. But it’s awfully annoying to have to hit up and enter over and over again, ins’t it? Well let me introduce you to the best feature in all of Postgres, and possibally the history of computer science. \watch was added in 9.3. Much like it’s Unix counterpart, it reruns the previous query for you over and over and over again. So if we run the select go command from earlier and add \watch 0.01 to the end, psql will show us the movie as a movie! Run it for yourself, or check out the video earlier to see what it looks like.

Michael Paquier: Postgres 12 highlight - Controlling SSL protocol

$
0
0

The following commit has happened in Postgres 12, adding a feature which allows to control and potentially enforce the protocol SSL connections can use when connecting to the server:

commit: e73e67c719593c1c16139cc6c516d8379f22f182
author: Peter Eisentraut <peter_e@gmx.net>
date: Tue, 20 Nov 2018 21:49:01 +0100
Add settings to control SSL/TLS protocol version

For example:

ssl_min_protocol_version = 'TLSv1.1'
ssl_max_protocol_version = 'TLSv1.2'

Reviewed-by: Steve Singer <steve@ssinger.info>
Discussion: https://www.postgresql.org/message-id/flat/1822da87-b862-041a-9fc2-d0310c3da173@2ndquadrant.com

As mentioned in the commit message, this commit introduces two new GUC parameters:

  • ssl_min_protocol_version, to control the minimal version used as communication protocol.
  • ssl_max_protocol_version, to control the maximum version used as communication protocol.

Those can also take different values, which defer depending on what the version of OpenSSL PostgreSQL is compiled with is able to support or not, with values going from TLS 1.0 to 1.3: TLSv1, TLSv1.1, TLSv1.2, TLSv1.3. An empty string can also be used for the maximum, to mean that anything is supported, which gives more flexibility for upgrades. Note that within a given rank, the latest protocol will be the one used by default.

Personally, I find the possibility to enforce that quite useful, as up to Postgres 11 the backend has been taking automatically the newest protocol available with SSLv2 and SSLv3 disabled by being hardcoded in the code. However sometimes there are requirements which pop up, telling to make sure that at least a given TLS protocol needs to be enforced. Such things would not matter for most users but for some large organizations sometimes it makes sense to enforce some control. This is also useful for testing a protocol when doing development on a specific patch, which can happen when working on things like SSL-specific things for authentication. Another area where this can be useful is if a flaw is found in a specific protocol to make sure that connections are able to fallback to a safer default, so flexibility is nice to have from all those angles.

From an implementation point of view, this makes use of a set of specific OpenSSL APIs to control the minimum and maximum protocols:

  • SSL_CTX_set_min_proto_version
  • SSL_CTX_set_max_proto_version

These have been added in OpenSSL 1.1.0, still PostgreSQL provides a set of compatibility wrappers which make use of SSL_CTX_set_options for older versions of OpenSSL, so this is not actually a problem when compiling with other versions, especially since OpenSSL 1.0.2 is the current LTS (Long-Time-Supported) version of upstream at this point.

Sebastian Insausti: PostgreSQL on the Rise: 2018 Postgres Findings & 2019 Trends

$
0
0

A strong community coupled with an increasingly stable and feature-rich platform are making PostgreSQL a strong contender for replacing the “big boys” of enterprise data. We here at Severalnines have also seen this trend and the growth of popularity of PostgreSQL. Below we will look at the future of PostgreSQL and why its growth is booming!

PostgreSQL Market Rise

According to DB-Engines PostgreSQL is the number four top database in use today and the number two most used open source database (behind MySQL). What’s interesting about this ranking however is the year-over-year score change that shows MySQL dropping in the triple digits while PostgreSQL is increasing by more than 75 points.

Database Rankings December 2018
Source: DB-Engines. Database Rankings December 2018

DB-Engines also declared PostgreSQL as the DBMS of the Year for 2017, the 2018 winner has not yet been announced.

The 2018 Stack Overflow survey found PostgreSQL ranked as number three as the top used database technologies behind MySQL and SQL Server. This is particularly interesting considering Stack Overflow is primarily a site for developers and in spite of this PostgreSQL is still preferred over MongoDB (which is a favorite amongst that audience).

Stack Overflow 2018 User Survey
Source: Stack Overflow 2018 User Survey

In an article titled Why Oracle's missteps have led to PostgreSQL's 'moment' in the database market” author Matt Asay said “Postgres is cool in part because of how great a database it is, and partly because it's the clearest like-for-like alternative to Oracle, which no one seems to want to use if they have any choice in the matter. No wonder, then, that out of all databases in existence, Postgres outperformed them all in terms of rising popularity.”

This sentiment was echoed by Tony Baer in his article Has the time finally come for PostgreSQL? , who said “it has become the go-to open source platform for third parties seeking to deliver their own relational database products. That is directly attributable to the conservative nature of the open source project that has prioritized stability and working nuts and bolts over bleeding edge flash.”

PostgreSQL Booming at Severalnines

Similar to what the market is seeing from a growth standpoint Severalnines is also seeing a boom in PostgreSQL interest.

PostgreSQL deployments and activations on ClusterControl have grown by 152% in 2018 (Download ClusterControl for Free) and web traffic has grown by nearly 3000% (yes that’s three zeros!) for Postgres content.

So what’s driving this increase? I’d say it’s several things. For one, as mentioned by Tony Baer above, PostgreSQL development over the past few years has really focused on improving the stability and functionality of the database rather than just churning out new features for the sake of flash. This was also true with the release of PostgreSQL 11 whose main features focused on improving indexing, partitioning, and a new stored procedures feature.

Top PostgreSQL Blogs of 2018

In line with the increased global interest in PostgreSQL in recent years, we decided to drum up our own contribution to the PostgreSQL community and started to create more PostgreSQL content also for our readers and users with the help of a team of specialist writers. Here are our top PostgreSQL blogs from 2018 …

  1. My Favorite PostgreSQL Queries and Why They Matter: This blog took off when an active debate started on Hackernews resulting in nearly 40K readers! The blog discusses extracting insight, answering questions, and meaningful metrics from data by way of querying and data manipulation is an integral component of SQL in general. This blog presents a combination of 8 interesting, differing PostgreSQL queries or types of queries to explore, study, learn, or otherwise manipulate data sets. The blog was followed up in July.
  2. A Performance Cheat Sheet for PostgreSQL: Performance tuning is not trivial, but you can go a long way with a few basic guidelines. In this blog, discussed how you analyze the workload of the database, and then review a list of important configuration parameters to improve the performance of PostgreSQL.
  3. PostgreSQL Privileges & User Management - What You Should Know: This blog demonstrates the basic PostgreSQL users and permissions.
  4. Deploying PostgreSQL on a Docker Container: This blog provides a high level overview and tips and tricks for deploying your PostgreSQL database on Docker.
  5. Migrating from Oracle to PostgreSQL - What You Should Know: This blog reviews what you would need to know if you decided to migrate from an Oracle database to PostgreSQL.

P.S. we are still looking for PostgreSQL guest writers to create even more content, if you are interested let us know!

Download the Whitepaper Today
 
PostgreSQL Management & Automation with ClusterControl
Learn about what you need to know to deploy, monitor, manage and scale PostgreSQL

New PostgreSQL ClusterControl Features in 2018

With four releases in 2018, ClusterControl has been expanding its support for PostgreSQL. Here are some of the top features released in the last year.

  • ClusterControl 1.5.1 (January)
    • Full backup and restore encryption for pg_dump and pg_basebackup
    • Improved user experience to make it easier to deploy and monitor PostgreSQL setups
  • ClusterControl 1.6 (April)
    • Easily deploy and manage PostgreSQL on public cloud instances like AWS, Google Cloud, and Azure
    • New topology viewer for PostgreSQL replication clusters
  • ClusterControl 1.6.1 (June)
    • New cloud deployment wizard for PostgreSQL
    • Automated deployment of synchronous replication slaves
    • PostgreSQL alerts & notifications with ServiceNow
  • ClusterControl 1.6.2 (July)
    • Continuous Archiving and Point-in-Time Recovery (PITR) for PostgreSQL
  • ClusterControl 1.7 (October)
    • Agent-based PostgreSQL monitoring with SCUMM
    • New PostgreSQL performance dashboard

Conclusion

So what does the future hold for PostgreSQL? Well, you don’t have to be a betting woman to know that their scheduled annual release of PostgreSQL 12 will come like clockwork this coming fall with a level of stability that its users have come to expect. It’s knowing that PostgreSQL is a database you can count on that continues to increase adoption and drive its use in the enterprise.

As for Severalnines? You can count on the fact that we will continue to improve support for PostgreSQL.

Bruce Momjian: Windows and Shared Buffers

$
0
0

Perhaps one overlooked change in Postgres 10 was the removal of the recommendation of smaller shared_buffers on Windows. This email thread discussed its removal. So, if you have been minimizing the size of shared_buffers on Windows, you can stop now.

Viewing all 9683 articles
Browse latest View live


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