How to prevent PostgreSQL to make uncontrolled checkpoints? - postgresql

I want to be able to disable PostgreSQL to auto checkpoint.
I just want to fsync wal files on disk without saving changes made in shared_buffer.
I set checkpoint_segments and checkpoint_timeout to big values, but still it makes additional checkpoints.
I don't want to checkpoint not even he needs to swap pages or is out of memory.

There are other causes for checkpoints:
Recovery has finished (could happen after a server crash).
Start of an online backup.
Database shutdown.
Before and after CREATE DATABASE.
After DROP DATABASE.
Before and after ALTER DATABASE SET TABLESPACE (you probably don't do that every day).
During DROP TABLESPACE (ditto).
And, of course, an explicit CHECKPOINT command.
I hope I haven't forgotten anything – could one of these cause the checkpoints you observe?
Set log_checkpoints to on, then the log file will show the cause of the checkpoint in the checkpoint starting message.
Are you sure that it is a good idea to avoid checkpoints? They are needed so that you can recover your database if there is a problem.

Related

Recover postgres deleted data before it checkpoints

If I understand correctly, when I delete a record and call commit, postgres will update write-ahead log (wal) and wait for the checkpoint then flush changes to the file.
My question is:
Is there any way I can recover deleted record after committed and before postgres checkpointing?
Btw, why is this method reducing disk write? Isn't wal an append log file?
I couldn't find anywhere how to do this without paying for postgres engineers.
Changes to the datafiles must be written and flushed by the end of the next checkpoint, but they can also be written earlier if the pages need to be (or are expected to be) evicted to make room for other data to be read in. As soon as the corresponding WAL is flushed, the change to the datafile is eligible to be written.
There is no user-available way to recover the deleted record. You could force a crash, then interfere with the recovery process. But you would have to be quite an expert to pull this off. It would be easier to just retrieve the record from a backup and then re-insert it. You don't even need to be an engineer to make this happen, just have valid backups (possibly including WAL archives) and know how to use them. Or better yet, don't commit things you don't want committed.
The system is designed this way for crash safety, not for reduced disk writing.

How long does pg_statio_all_tables data live for?

I have read https://www.postgresql.org/docs/current/monitoring-stats.html#MONITORING-PG-STATIO-ALL-TABLES-VIEW
But it does not clarify whether this data is over the whole history of the DB (unless you reset the stats counters). Or whether it is just for recent data.
I am seeing a low cache-hit ratio on one of my tables, but I recently added an index to it. I'm not sure if it is low from all the pre-index usage, or if it is still low, even with the index.
Quote from the manual
When the server shuts down cleanly, a permanent copy of the statistics data is stored in the pg_stat subdirectory, so that statistics can be retained across server restarts. When recovery is performed at server start (e.g., after immediate shutdown, server crash, and point-in-time recovery), all statistics counters are reset.
I read this as "the data is preserved as long as the server is restarted cleanly".
So the data is only reset if recovery was performed or it has been reset manually using pg_stat_reset ().

Debezium causes Postgres to run out of disk space on RDS

I have a small Postgres development database running on Amazon RDS, and I'm running K8s. As far as I can tell, there is barely any traffic.
I want to enable change capture, I've enabled rds.logical_replication, started a Debezium instance, and the topics appear in Kafka, and all seems fine.
After a few hours, the free disk space starts tanking:
It started to consume disk at a constant rate, and eat up all of the 20Gb available within 24 hours. Stopping Debezium doesn't do anything. The way I got my disk space back was by:
select pg_drop_replication_slot('services_debezium')
and:
vacuum full
Then, after a few minutes, as you can see in the graph, disk space is reclaimed.
Any tips? I would love to see what is it what's actually filling up the space, but I don't think I can. Nothing seems to happen on the Debezium side (no ominous logs), and the Postgres logs don't show anything special either. Or is there some external event that triggers the start of this?
You need to periodically generate some movement in your database (perform an update on any record for example).
Debezium provides a feature called heartbeat to perform this type of operation.
Heartbeat can be configured in the connector as follows:
"heartbeat.interval.ms" : "300000",
"heartbeat.action.query": "update my_table SET date_column = now();"
You can find more information in the official documentation:
https://debezium.io/documentation/reference/connectors/postgresql.html#postgresql-wal-disk-space
The replication slot is the problem. It marks a position in the WAL, and PostgreSQL won't delete any WAL segments newer than that. Those files are in the pg_wal subdirectory of the data directory.
Dropping the replication slot and running CHECKPOINT will delete the files and free space.
The cause of the problem must be misconfiguration of Debrezium: it does not consume changes and move the replication slot ahead. Fix that problem and you are good.
Ok, I think I figured it out. There is another 'hidden' database on Amazon RDS, that has changes, but changes that I didn't make and I can's see, so Debezium can't pick them up either. If change my monitored database, it will show that change and in the process flush the buffer and reclaim that space. So the very lack of changes was the reason it filled up. Don't know if there is a pretty solution for this, but at least I can work with this.

Is there a system procedure or method to find out transaction log full issue?

I'm looking for a easy method to find the culprit process holding the transaction log which is causing the pg_wal full isues.
The transaction log contains all transactions, and it does not contain a reference to the process that caused an entry to be written. So you cannot infer from WAL what process causes the data modification activity that fills your disk.
You can turn on logging (log_min_duration_statement = 0) and find the answer in the log file.
But I think that you are looking at the problem in the wrong way: the problem is not that WAL is generated, but that full WAL segments are not removed soon enough.
That can happen for a variety of reasons:
WAL archiving has problems or is too slow
a stale replication slot is blocking WAL removal
wal_keep_segments is too high

Can PostgreSQL be configured so that occasional mass updates can run super-fast?

I have setup a PostgreSQL test environment which is required to contain the same amount of data (number of rows) as the production database, and be configured mostly production-like to simulate the same performance for normal transactions.
However, it being a test environment, occasionally has to have some unique, experimental, temporary, or ad-hoc changes applied. For instance, adding or removing some indexes before a performance test, recalculating the value of a column to replicate test conditions, dumping and reimporting whole tables, etc.
Is there a way to temporarily suspend data integrity guarantees in order to perform such types of mass update as fast as possible?
For example, in MySQL you can set over-sized write buffers, disable transaction logging, and suspend disk flushes on transaction commit. Is there something similar in pgsql?
The deployment environment is AWS EC2.
The manual has a chapter dedicated to initial loading of a database.
There are some safe options you can change to make things faster:
increasing max_wal_size
increasing checkpoint_timeout
wal_level to minimal
wal_log_hints to off
synchronous_commit to off
Then there are some rather unsafe options to make things faster. Unsafe meaning: you can lose all your data if the server crashes - so use at your own risk!
full_page_writes to off
fsync to off
Again: by changing the two settings above, you risk losing all your data.
To disable WAL you could also set all tables to unlogged
You can disable WAL logging with ALTER TABLE ... SET UNLOGGED, but be aware that the reverse operation will dump the whole table to WAL.
If that is not feasible, you can boost performance by setting max_wal_size hugh so that you get fewer checkpoints.
WAL flushing is disabled by setting fsync = off.
Be aware that the first and third measure will wreck your database in the event of a crash.