Does dropping a database have to be done not in any transaction? - postgresql

From https://wiki.postgresql.org/wiki/Psycopg2_Tutorial
PostgreSQL can not drop databases within a transaction, it is an all
or nothing command. If you want to drop the database you would need to
change the isolation level of the database this is done using the
following.
conn.set_isolation_level(0)
You would place the above immediately preceding the DROP DATABASE
cursor execution.
Why "If you want to drop the database you would need to change the isolation level of the database"?
In particular, why do we need to change the isolation level to 0? (If I am correct, 0 means psycopg2.extensions.ISOLATION_LEVEL_READ_COMMITTED)
From https://stackoverflow.com/a/51859484/156458
The operation of destroying a database is implemented in a way which
prevents undoing it - therefore you can not run it from inside a
transaction because transactions are always undoable. Also keep in
mind that unlike most other databases PostgreSQL allows almost all DDL
statements (obviously not the DROP DATABASE one) to be executed inside
a transaction.
Actually you can not drop a database if anyone (including you) is
currently connected to this database - so it does not matter what is
your isolation level, you still have to connect to another database
(e.g. postgres)
"you can not run it from inside a transaction because transactions are always undoable". Then how can I drop a database not from inside a transaction?
I found my answer at https://stackoverflow.com/a/51880577/156458

I'm unfamiliar with psycopg2 so I can only provide steps to be performed.
Steps to be taken to perform DROP DATABASE from Python:
Connect to a different database, which you don't want to drop
Store current isolation level in a variable
Set isolation level to 0
Execute DROP DATABASE query
Set isolation level back to original (from #2)
Steps to be taken to perform DROP DATABASE from PSQL:
Connect to a different database, which you don't want to drop
Execute DROP DATABASE query
Code in psql
\c second_db
DROP DATABASE first_db;
Remember, that there can be no live connections to the database you are trying to drop.

Related

Lock table on postgresql 9.6

i'm new in postgres administration and when developper run LOCK TABLE tab1; with PREPAREDstatement , postgres use ACCES EXCLUSIVE BY DEFAULT. My probelem is that the lock in table is still here after one week in view pg_prepared_xact and pg_locks even after restart of postgres and in pg_lock is like:
vXID mode
-1/192836 AccessExclusiveLock
Name DATABASE Owner XID prepared at
db1 postgres 192836 20-07-2021
I would know why the LOCK is still here?? and how to solve it? and what is mean -1 in vXID?? because i can't even show my data on tab1
with PREPARED statement
Prepared transactions and prepared statements are very different things. What you have here is a prepared transaction. Surviving a restart is what prepared transactions are for. You need to find its "gid" in pg_prepared_xacts and then either manually commit it or roll it back. If you are not intentionally using prepared transactions, the you should set max_prepared_transactions =0, so this can't recur. If you are intentionally using them, you need to learn how to handle them.

FireDAC: Shared Lock on Table with Firebird

I'm using Delphi 10.1 with FireDAC to connect to Firebird.
I would like to open a table in Exclusive mode in Firebird with FireDAC?
How would it be?
Firebird does not handle table or row locks. So there's no way you're going to get this to work with FireDAC... no connection parameters can do this magic.
What you can do with Firebird is to use the entire database in single user mode. To do this, you must shut it down, run GFIX to flag it as a single user database, and then reconnect to the database. You can find more details on the Firebird How-To FAQ. But I doubt this is what you are looking for.
You should explain better what you are trying to do. With real SQL servers you should not feel the need to lock tables or rows. Transactions and transaction isolation should be enough to handle most situations. If not, then you should probably start thinking about application level locks, that is, if you have just one application that uses the database.

Run Alter Database with Set READ_COMMITTED_SNAPSHOT to ON

I am trying to run the SQL statement below:
ALTER DATABASE DBNAME
SET READ_COMMITTED_SNAPSHOT ON
However when I ran it does not complete the execution I have to terminate after an 1hr.
Is there any suggestion on how to run this without disconnecting all other user from the database?
Thanks
Completion of this command requires, for just an instant, to be the only transaction open against the database. It seems to me that this almost requires that you put the DB into single-user mode briefly. But maybe if you just leave the query (trying to) run overnight, at some point you'll get that magic instant.
There's a bit more on the topic here: http://www.brentozar.com/archive/2013/01/implementing-snapshot-or-read-committed-snapshot-isolation-in-sql-server-a-guide/
Edit: the books online offers a bit more detail:
When you set ALLOW_SNAPSHOT_ISOLATION to a new state (from ON to OFF, or from OFF to ON), ALTER DATABASE does not return control to the caller until all existing transactions in the database are committed. If the database is already in the state specified in the ALTER DATABASE statement, control is returned to the caller immediately. If the ALTER DATABASE statement does not return quickly, use sys.dm_tran_active_snapshot_database_transactions to determine whether there are long-running transactions. If the ALTER DATABASE statement is canceled, the database remains in the state it was in when ALTER DATABASE was started. The sys.databases catalog view indicates the state of snapshot-isolation transactions in the database. If snapshot_isolation_state_desc = IN_TRANSITION_TO_ON, ALTER DATABASE ALLOW_SNAPSHOT_ISOLATION OFF will pause six seconds and retry the operation.

FDW seems to lock table on foreign server

I try to use foreign table to link 2 postgresql databases
everything is fine and I can retrieve all data I want
the only issue is that the data wrapper seems to lock tables in foreign server and it's very annoying when I unit test my code
if I don't do any select request I can initialize data and truncate both tables in local server and tables in remote server
but I execute one select statement the truncate command on remote server seems to be in deadlock state
do you know how I can avoid this lock?
thanks
[edit]
I use this data wrapper to link 2 postgresql databases: http://interdbconnect.sourceforge.net/pgsql_fdw/pgsql_fdw-en.html
I use table1 of db1 as foreign table in db2
when I execute a select query in foreign_table1 in db2, there is an AccessShareLock for table1 in db1
the query is very simple: select * from foreign_table1
the lock is never released so when I execute a truncate command at the end of my unit test, there is a conflict because the truncate add an AccessExclusiveLock
I don't know how to release the first AccessShareLock but I think it would be done automatically by the wrapper...
hope this help
AccessExclusiveLock and AccessShareLock aren't generally obtained explicitly. They're obtained automatically by certain normal statements. See locking - the lock list says which statements acquire which locks, which says:
ACCESS SHARE
Conflicts with the ACCESS EXCLUSIVE lock mode only.
The SELECT command acquires a lock of this mode on referenced tables.
In general, any query that only reads a table and does not modify it
will acquire this lock mode.
What this means is that your 1st transaction hasn't committed or rolled back (thus releasing its locks) yet, so the 2nd can't TRUNCATE the table because TRUNCATE requires ACCESS EXCLUSIVE which conflicts with ACCESS SHARE.
Make sure the 1st transaction commits or rolls back.
BTW, is the "foreign" database actually the local database, ie are you using pgsql_fdw as an alternative to dblink to simulate autonomous transactions?

Sync transactions between databases in PostgreSQL using dblink

I would like to sync a set of tables between two databases, transparently without application code chages. My idea is to create triggers on insert, update and delete, in the source database tables to replicate the data using dblink to the dest. database tables seamlessly.
The problem is that changes in the source tables are always done inside a transaction. The triggers automatically replicate changes in the dest. tables but if the source transaction is rolled back the dest. tables changes are not.
Is there a way to automatically sync transaction begin and commit/rollback between the two databases? A trigger-like behavior would be ideal.
Yes, it's possible from ages - using Slony-I, or other trigger-based replication.
Row updates are logged to special tables on "master" side, and replayed asynchronously on "slave" side.
External program/daemon is used to synchronise changes.
See http://www.postgresql.org/docs/current/static/different-replication-solutions.html and http://wiki.postgresql.org/wiki/Replication,_Clustering,_and_Connection_Pooling#Replication for more information.
When 9.3 comes out, check out http://www.postgresql.org/docs/9.3/static/postgres-fdw.html. You can roll back transactions in foreign databases.