Error cannot execute insert in a read only transaction

I am using PostgreSQL server and suddenly I am getting this error. Due to that, I am not able to insert data into any table. org.postgresql.util.PSQLException: ERROR: cannot execute INSERT in a r...

I am using PostgreSQL server and suddenly I am getting this error. Due to that, I am not able to insert data into any table.

org.postgresql.util.PSQLException: ERROR: cannot execute INSERT in a read-only transaction

I have checked solution online and found that the default_transaction_read_only parameter needs to be set to off but it is off already.

Laurenz Albe's user avatar

Laurenz Albe

192k17 gold badges177 silver badges233 bronze badges

asked May 5, 2019 at 14:05

DeepInJava's user avatar

4

Log on to PostgreSQL and verify if your database is in recovery mode or not with below command :-

  • select pg_is_in_recovery();

pg_is_in_recovery() should be false(f)

  • If the above value is true, intimate admin to move the DB out of recovery mode.

Further check if default transaction is read-only or read-write with below command :-

  • show default_transaction_read_only;

default_transaction_read_only must be «off»

  • If the value is not off, run the below command
  • psql -U username -d postgres begin; alter database dbname set
    default_transaction_read_only = off; commit; q

If issue persists after performing the above fix, please check on the connection setting and make sure to use hostname rather than host IP in place of jdbcUrl

answered Oct 26, 2021 at 18:44

arun's user avatar

arunarun

577 bronze badges

Skip to content

In this article, we will see the solution for error like PostgreSQL Error: cannot execute in a read-only transaction.

ERROR: cannot execute CREATE DATABASE in a read-only transaction Error: cannot execute DROP DATABASE in a read-only transaction ERROR: cannot execute CREATE TABLE in a read-only transaction Error: cannot execute DROP TABLE in a read-only transaction cannot execute INSERT in a read-only transaction

PostgreSQL Error cannot execute in a read-only transaction


Reason:

Reason is simple, PostgreSQL server is recovery(read-only) or standby mode.

Resolution:

1. We have to remove recovery(read-only) or standby mode.

2. Go to your data or main directory then remove standby.signal and recovery.signal files.

Before performing following action, take backup of these files in some other location.

File location in(Ubuntu change your respective version nuymber)

/var/lib/postgresql/13/main

3. After removing signal files, restart PostgreSQL cluster.

sudo systemctl restart postgresql

4. Then, you will able to connect to the server and perform all actions as usual.


Sun, Jan 23, 2022

2-minute read

Typically when discussing having “read-only” connections to a PostgreSQL database, it is in the context of connecting to a replica.

There are a variety of methods available to route connections with known read-only queries (i.e. queries with SELECT statements…that are not calling VOLATILE functions that modify data). This includes connection proxy software like Pgpool-II or framework mechanisms such as Django’s database router.

However, there are situations where you might need to force read-only connections to your primary (read-write) Postgres instance. Some examples include putting your application into a degraded state to perform a database move or upgrade, or allowing an administrator to inspect a system that may be accumulating write-ahead logs that track all changes to the system.

PostgreSQL has a configuration parameter call default_transaction_read_only. Setting default_transaction_read_only globally to on forces all connections to disallow writes to the database. default_transaction_read_only is a reloadable parameter, so you do not need to restart your Postgres instance to use it.

Here is a quick example of how default_transaction_read_only works. First, ensure your system does not have default_transaction_read_only set:

postgres=# SHOW default_transaction_read_only ;

 default_transaction_read_only
-------------------------------
 off
(1 row)

postgres=# CREATE TABLE IF NOT EXISTS abc (id int); INSERT INTO abc VALUES (1) RETURNING id;
CREATE TABLE

 id
----
  1
(1 row)

INSERT 0 1

This works as expected: we’re able to create a table and insert data. Now let’s put the system into default_transaction_read_only mode (note that I am running this on PostgreSQL 14)

ALTER SYSTEM SET default_transaction_read_only TO on;
SELECT pg_reload_conf();
SHOW default_transaction_read_only;

Ensure that default_transaction_read_only is enabled:

postgres=# SHOW default_transaction_read_only;

 default_transaction_read_only
-------------------------------
 on
(1 row)

Now verify that writes are disallowed:

postgres=# INSERT INTO abc VALUES (2) RETURNING id;
ERROR:  cannot execute INSERT in a read-only transaction

Excellent!

Note that default_transaction_read_only is not a panacea: there are some caveats that you should be aware of.

First, default_transaction_read_only can be overriden in a session, even if the value is set database-wide. For example:

postgres=# SHOW default_transaction_read_only ;
 default_transaction_read_only
-------------------------------
 on
(1 row)

postgres=# SET default_transaction_read_only TO off;
SET

postgres=# INSERT INTO abc VALUES (2) RETURNING id;

 id
----
  2
(1 row)

INSERT 0 1

Second, when utilizing default_transaction_read_only with an application, you must also ensure your app can be configured to send only read queries to the database, ensuring a smooth user experience.

That said, if you have a situation where you need to put a PostgreSQL primary instance into a “read-only” mode temporarily, you can use default_transaction_read_only to prevent write transactions.

Существует несколько типов методов реализации, которые заблокированы.

1. Жесткий замок, напрямую переключите базу данных в режим восстановления, абсолютно не имеют операции записи.

2, Soft Lock, установите значение default_transaction_read_only on, транзакция по умолчанию используется транзакция только для чтения. Пользователи могут быть взломаны, если вы используете The Begion Transaction Read Write.

1 экземпляр блокировки

Жесткий замок

1, настройте Recovery.conf

recovery_target_timeline = 'latest'  
standby_mode = on  

2, перезапустите базу данных

pg_ctl restart -m fast  

3, жесткий замок, не может треснуть

postgres=# select pg_is_in_recovery();  
 pg_is_in_recovery   
-------------------  
 t  
(1 row)  
  
postgres=# insert into t1 values (1);  
ERROR:  cannot execute INSERT in a read-only transaction  
  
postgres=# begin transaction read write;  
ERROR:  cannot set transaction read-write mode during recovery  

Мягкий замок

1, установить default_transaction_read_only

postgres=# alter system set default_transaction_read_only=on;  
ALTER SYSTEM  

2, конфигурация перегрузки

postgres=# select pg_reload_conf();  
 pg_reload_conf   
----------------  
 t  
(1 row)  

3. Все сеансы автоматически входят в режим транзакции по умолчанию только для чтения.

До перезагрузки

postgres=# show default_transaction_read_only ;  
 default_transaction_read_only   
-------------------------------  
 off  
(1 row)  

После перезагрузки

postgres=# show default_transaction_read_only ;  
 default_transaction_read_only   
-------------------------------  
 on  
(1 row)  
  
postgres=# insert into t1 values (1);  
ERROR:  cannot execute INSERT in a read-only transaction  

4, мягкий замок может быть сломан

postgres=# begin transaction read write;  
BEGIN  
postgres=# insert into t1 values (1);  
INSERT 0 1  
postgres=# end;  
COMMIT  

2 разблокирован пример

Жесткий смысл замок

1, переименовать Recovery.conf на Recovery.done

cd $PGDATA  
  
mv recovery.conf recovery.done  

2, перезапустите базу данных

pg_ctl restart -m fast  

Мягкая блокировка

1, установить default_transaction_read_only

postgres=# alter system set default_transaction_read_only=off;  
ALTER SYSTEM  

2, конфигурация перегрузки

postgres=# select pg_reload_conf();  
 pg_reload_conf   
----------------  
 t  
(1 row)  

3. Все сеансы автоматически входят в режим транзакции по умолчанию только для чтения.

До перезагрузки

postgres=# show default_transaction_read_only ;  
 default_transaction_read_only   
-------------------------------  
 on  
(1 row)  

После перезагрузки

postgres=# show default_transaction_read_only ;  
 default_transaction_read_only   
-------------------------------  
 off  
(1 row)  
  
Пишите восстановление  
postgres=# insert into t1 values (1);  
INSERT 0 1  

Normally the most plausible reasons for this kind of error are :

  • trying create statements on a read-only replica (the entire instance is read-only).

  • <username> has default_transaction_read_only set to ON

  • the database has default_transaction_read_only set to ON

The script mentioned has in its first lines:

CREATE DATABASE exercises;
c exercises
CREATE SCHEMA cd;

and you report that the error happens with CREATE SCHEMA at line 6, not before.

That means that the CREATE DATABASE does work, when run by <username>.
And it wouldn’t work if any of the reasons above was directly applicable.

One possibility that would technically explain this would be that default_transaction_read_only would be ON in the postgresql.conf file, and set to OFF for the database postgres, the one that the invocation of psql connects to, through an ALTER DATABASE statement that supersedes the configuration file.

That would be why CREATE DATABASE works, but then as soon as it connects to a different database with c, the default_transaction_read_only setting of the session would flip to ON.

But of course that would be a pretty weird and unusual configuration.

Reached out to pgexercises.com and they were able to help me.

I ran these commands(separately):

psql -U <username> -d postgres
begin;
set transaction read write;
alter database exercises set default_transaction_read_only = off;
commit;
q

Then I dropped the database from the terminal dropdb exercises and ran script again psql -U <username> -f clubdata.sql -d postgres -x -q

I had same issue for Postgre Update statement

SQL Error: 0, SQLState: 25006 ERROR: cannot execute UPDATE in a read-only transaction

Verified Database access by running below query and it will return either true or false

SELECT pg_is_in_recovery()

true -> Database has only Read Access

false -> Database has full Access

if returns true then check with DBA team for the full access and also try for ping in command prompt and ensure the connectivity.

ping <database hostname or dns>

Also verify if you have primary and standby node for the database

I was having getting cannot execute CREATE TABLE in a read-only transaction, cannot execute DELETE TABLE in a read-only transaction and others.

They all followed a cannot execute INSERT in a read-only transaction. It was like the connection had switched itself over to read-only in the middle of my batch processing.

Turns out, I was running out of storage! Write access was disabled when the database could no longer write anything. I am using Postgres on Azure. I don’t know if the same effect would happen if I was on a dedicated server.

Понравилась статья? Поделить с друзьями:
  • Error cannot execute drop database in a read only transaction
  • Error cannot execute delete in a read only transaction
  • Error cannot execute create function in a read only transaction
  • Error cannot enqueue query after invoking quit
  • Error cannot enqueue query after fatal error