T-SQL unfinished transaction lock - tsql

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.

Related

Cannot rename database due to prepared transactions

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.

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.

What is a good way of rolling back a transaction in Postgres

I want to insert data into a table from a staging table but keep the data unchanged if an error happens.
What I have is a working happy path
Begin transaction;
DELETE FROM mytable;
INSERT INTO mytable SELECT * FROM mytable_staging ;
Commit transaction;
In case the insert statement is failing how can I rollback the transaction?
PostgreSQL transactions will roll back on error automatically, see this.
Atomicity − Ensures that all operations within the work unit are
completed successfully; otherwise, the transaction is aborted at the
point of failure and previous operations are rolled back to their
former state.
Consistency − Ensures that the database properly changes states upon a
successfully committed transaction.
Isolation − Enables transactions to operate independently of and
transparent to each other.
Durability − Ensures that the result or effect of a committed
transaction persists in case of a system failure.
You can rollback a Postgres transaction using the ROLLBACK [WORK | TRANSACTION] statement:
Begin transaction;
DELETE FROM mytable;
INSERT INTO mytable SELECT * FROM mytable_staging ;
Rollback transaction;
All the SQL commands are case-insensitive and the transaction part of the statement is optional, but I like to include it for clarity.

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?

Create a stored procedure in PostgreSQL that is never rolled back?

From the PostgreSQL 9.0 manual:
Important: To avoid blocking concurrent transactions that obtain
numbers from the same sequence, a nextval operation is never rolled
back; that is, once a value has been fetched it is considered used,
even if the transaction that did the nextval later aborts. This means
that aborted transactions might leave unused "holes" in the sequence
of assigned values. setval operations are never rolled back, either.
So, how can I create a PL\PgSQL function with the same behaviour: "operation is never rolled back"?
In a call like this, whatever the function changes will NOT be rolled back:
BEGIN;
SELECT composite_nextval(...);
ROLLBACK;
You can use a savepoint after selecting composite_nextval. Then, just rollback to that savepoint and commit the rest.
Something like this:
BEGIN;
SELECT composite_nextval(...);
SAVEPOINT my_savepoint;
INSERT INTO some_table(a) VALUES (2);
ROLLBACK TO SAVEPOINT my_savepoint;
COMMIT;
This way, select composite_nextval(...) will be committed, but insert into some_table will not.