Cannot rename database due to prepared transactions - postgresql

I'm trying to rename a database using:
ALTER DATABASE xxx RENAME TO yyy
I got an error message saying there is another open session. I killed it using:
SELECT pg_terminate_backend(pg_stat_activity.pid)
FROM pg_stat_activity
WHERE pg_stat_activity.datname = 'xxx' AND pid <> pg_backend_pid();
However, I then got an error message saying there are 2 prepared transactions pending. I made sure to kill all processes in the background with:
SELECT pg_cancel_backend(pid) FROM pg_stat_activity WHERE pid <> pg_backend_pid();
But still, I am not able to rename the database.
I then saw there is a view by postgres called pg_prepared_xacts that shows me the prepared transactions (shortened the gid for a better overview), and indeed, there are two of them:
transaction|gid |prepared |owner|database|
-----------+--------------+-----------------------------+-----+--------+
5697779 |4871251_EAAAAC|2022-08-05 15:50:59.782 +0200|xxx |xxx |
5487701 |4871251_DAAAAA|2022-07-08 08:05:36.066 +0200|xxx |xxx |
According to the Postgres documentation on prepared transactions, I can execute a Rollback on the transaction id - which is what I did:
ROLLBACK PREPARED '5697779';
I made sure to execute the ROLLBACK with the same user, but it shows an error message saying that the transaction does not exist...
How can I get rid of it / kill it in order to be able to rename the database?
Thank you for reading and taking time to respond.

From here Prepared transaction:
transaction_id
An arbitrary identifier that later identifies this transaction for COMMIT PREPARED or ROLLBACK PREPARED. The identifier must be written as a string literal, and must be less than 200 bytes long. It must not be the same as the identifier used for any currently prepared transaction.
and from here Rollback prepared:
transaction_id
The transaction identifier of the transaction that is to be rolled back.
Lastly from here pg_prepared_xacts:
gid text
Global transaction identifier that was assigned to the transaction
So to rollback the transaction you need the global identifier assigned in the PREPARE TRANSACTION as shown in the gid column in pg_prepared_xacts.

Related

Postgresql - Unable to see exact Query or Transaction that blocked my actual Transaction

Note: I'm using DBeaver 21.1.3 as my PostgreSQL development tool.
For my testing, I have created a table:
CREATE TABLE test_sk1(n numeric(2));
then I have disabled Auto-Commit on my DBEaver to verify whether I can see the blocking query for my other transaction.
I have then executed an insert on my table:
INSERT INTO test_sk1(n) values(10);
Now this insert transaction is un-committed, which will block the table.
Then I have taken another new SQL window and tried alter command on the table.
ALTER TABLE test_sk1 ADD COLUMN v VARCHAR(2);
Now I see the alter transaction got blocked.
But when I verified in the locks, I see that this Alter transaction got blocked by "Show search_path;' transaction, where I'm expecting "INSERT..." transaction as blocking query.
I used below query to fetch the lock:
SELECT p1.pid,
p1.query as blocked_query,
p2.pid as blocked_by_pid,
p2.query AS blocking_query
FROM pg_stat_activity p1, pg_stat_activity p2
WHERE p2.pid IN (SELECT UNNEST(pg_blocking_pids(p1.pid)))
AND cardinality(pg_blocking_pids(p1.pid)) > 0;
Why is this happening on our databases?
Try using psql for such experiments. DBeaver and many other tools will execute many SQL statements that you didn't intend to run.
The query that you see in pg_stat_activity is just the latest query done by that process, not necessarily the one locking any resource.

Getting SQL state: 25P02 while trying to update a table with data from another

I am using a PostgreSQL DB. I have two tables, namely company and bl_location. I have a field location_id in both tables. Now I am trying to copy the value of location_id from bl_location to company. The primary key of company is company_id and it is stored in bl_location too. I am trying the following query:
UPDATE company
SET location_id = bl_location.location_id
from bl_location
where company.company_id = bl_location.company_id;
using the syntax I found online:
update table1
set col1 = . . .
from table2
where table1.id = table2.table1_id
But I am getting the following in the console of the pgAdmin tool:
ERROR: current transaction is aborted, commands ignored until end of transaction block
********** Error **********
ERROR: current transaction is aborted, commands ignored until end of transaction block
SQL state: 25P02
I cannot figure out what is wrong with my query.
RCA : This issue happens when last transitions ended up with error and not rolled back
FIX : psql > ROLLBACK
if you're using PGAdmin click on rollback & enable auto rollback option
Whether you are aware of it or not, your statement is running inside an explicit transaction, and one of the preceeding statements is the same transaction must have caused an error.
To debug this, consider setting log_statement = 'all' so that all statments get logged. By tracing all statements from the same backend PID you will be able to identify the culprit.

Why does pgsql claim the currval of sequence undefined even after calling nextval?

I'm working with a PostgresQL database, in which a trigger function logs changes to a history table. I'm trying to add a column which keeps a logical "commit ID" to group master and detail records together. I've created a (non-temporary) sequence, and before I start the batch of updates, I bump this. All my SQL is logged to a log file, so you can clearly see this happening:
2015-04-16 10:43:37 SQLSelect: SELECT nextval('commit_id_seq')
2015-04-16 10:43:37 commit_id_seq: 8
...but then I attempt the UPDATE, my trigger function attempts to use currval, and it fails:
2015-04-16 10:43:37 ERROR: ERROR: currval of sequence "commit_id_seq" is not yet defined in this session
CONTEXT: SQL statement "INSERT INTO history (table_name, record_id, sec_user_id, created, action, notes, status, before, after, commit_id)
SELECT TG_TABLE_NAME, rec.id, (SELECT oid FROM pg_roles WHERE rolname = CURRENT_USER), now(), SUBSTR(TG_OP,1,1), note, stat, hstore(old), hstore(new), currval('commit_id_seq')"
PL/pgSQL function log_to_history() line 18 at SQL statement
[3]
So my question is basically: WTF?
One of two reasons:
Search_path differences, so you're actually talking about two different sequences.
Different sessions. The "current value" is only defined for the session you call nextval() in.
You can add process-id to the logfile format to check if they are different sessions.

Why my sp deadlocked in a transaction?

This is what the sp does:
SET TRANSACTION ISOLATION LEVEL Serializable
begin transaction
IF EXISTS( SELECT 1 FROM dbo.Portfolio WHERE RawMessageID = #RawMessageID)
begin
----do some cleaning job like delete the portfolio, or something
end
insert into Portfolio
select #a,#b,#c,#d
commit
Randomly, I see deadlock happen and this deadlock graph showing the detail.
So it has to be that one instance of the call hold the shared lock from the select statement and asking for an null resource lock. Another instance holds the null resource lock and asks for shared lock.
Is my guess right? I was trying to write an simplified version to demo this, but never can trigger this deadlock.
Can someone help?

T-SQL unfinished transaction lock

I tried to run the following query
BEGIN TRANSACTION t1
SET IDENTITY_INSERT existingTableA On
insert INTO existingTableA (columnsFromTableA)
SELECT (columnsFromIdenticalTableB) from column identicalTableB
problem is that I didn't commit the transaction explicitly and it appears that I cannot do it any more and it's still ongoing. the select operation from tableA never ends because of the lock I cannot kill ("Distributed transaction with UOW {2B9A3B1B-F3EF-4C5A-9AD8-F434EF9EA3EC} is in prepared state. Only Microsoft Distributed Transaction Coordinator can resolve this transaction. KILL command failed.")
how do I end that transaction?
Run DBCC OPENTRAN.
Then kill the open Transaction with KILL xx, where xx is the SPID.