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
192k17 gold badges177 silver badges233 bronze badges
asked May 5, 2019 at 14:05
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
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
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>
hasdefault_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.