select table from AccessExclusiveLock locked table - postgresql

I'm testing postgresql lock mechanism on my pgsql-9.1 on centos-5.8.
What I'm wondering is how can I select from table which is exclusively locked caused by <IDLE> in transaction uncommited.
The case is below...
In session1
postgres=# create table test_table(col1 char);
CREATE TABLE
postgres=# begin;
BEGIN
postgres=# insert into test_table values('1');
INSERT 0 1
--uncommited
In session2
postgres=# alter table test_table add column c2 char;
-- It has been locked....
in session3
postgres=# select t.relname, l.locktype,page,pid,virtualtransaction,mode,granted from pg_locks l, pg_stat_all_tables t where l.relation=t.relid order by relation asc;
relname | locktype | page | pid | virtualtransaction | mode | granted
--------------+----------+------+------+--------------------+---------------------+---------
pg_class | relation | | 9940 | 2/715754 | AccessShareLock | t
pg_index | relation | | 9940 | 2/715754 | AccessShareLock | t
pg_namespace | relation | | 9940 | 2/715754 | AccessShareLock | t
test_table | relation | | 9660 | 9/671042 | RowExclusiveLock | t
test_table | relation | | 9639 | 7/707191 | AccessExclusiveLock | f
(5 rows)
postgres=# select col1 from test_table;
--It's not possible to select from exclusively locked table
What I need is to get size of the relation regardless of locking happened.
I'm bushing around set transaction isolation level but I didn't catch any solutions till now.
Any advice would be very appreciated.
Thanks in advance.

Your table is not access exclusively locked, it has an AccessExclusiveLock pending but not granted, behind a granted AccessShareLock. Although it does have about the same effect, new AccessShareLock queue up behind it. They could in theory jump the queue and be granted, but that risks the starvation of AccessExclusiveLock requests so it is not done.
If an estimate is good enough, you could do
select reltuples from pg_class where oid='test_table'::regclass;
Otherwise, about the only options is to kill one of the two processes that is holding the table lock hostage, either the one holding the AccessShare or the one wanting the AccessExclusive. (Or hack the PostgreSQL source code.)

Related

changing permission of table in postgresql

I took postgresql dump and restore it in another db. I am trying to change the permission of the table in the secondary db. But I am not change the permission can't evn view individual table.
Whenever I list all the tables in a Scheme I can get the results but when i search for individual tables getting below error.
select \* from pg_tables where schemaname='testing';
schemaname | tablename | tableowner | tablespace | hasindexes | hasrules | hastriggers | rowsecurity
\------------+-----------------+------------+------------+------------+----------+-------------+-------------
testing | chatting | postgres | | t | f | t | f
testing | report | postgres | | t | f | f | f
select chatting from pg_tables where schemaname='testing';
ERROR: column "chatting" does not exist
LINE 1: select channel from pg_tables where schemaname='testing';
Can someone help me on this? I would like to change the owner of all the tables in this schema to a different user.
Note: I haven't create the tables, it is part of the pg_dump.
The query that you should run is
select * from pg_tables where schemaname='testing' and tablename = 'chatting';

Postgres query is getting lock while executing through shell script

The below query is getting locked by executing through perl
ALTER TABLE base_table
DETACH PARTITION part_table;
By using this query
select pid,state,
usename,
pg_blocking_pids(pid) as blocked_by,
query as blocked_query
from pg_stat_activity
where cardinality(pg_blocking_pids(pid)) > 0;
pid | state | usename | blocked_by | blocked_query
-------+--------+----------+------------+------------------------------------
20521 | active | parttest | {20306} | ALTER TABLE BASE +
| | | | DETACH PARTITION part_table
| | | |
(1 row)
Can you please suggest me how to solve this issue?

Size of temp tables created in a particular session

I created a temp table using below query
Drop table if exists tmp_a;
Create temp table tmp_a
(
id int
);
Insert into tmp_a select generate_series(1,10000);
When I queried pg_stat_activity, it is showing as "IDLE" in current_query column for the above session.
I will get the size of all temp table from pg_class table using this query.
But I want the list of temp tables created for a particular session and the size of those temp tables i.e if I created two temp tables from two different sessions then the result should be like below
procpid | temp table name | size | username
12345 | tmp_a | 20 | gpadmin
12346 | tmp_b | 30 | gpadmin
Please share the query if anyone has it
It's actually simpler than you think --
The temporary schema namesapce is the same as the session id --
So...
SELECT
a.procpid as ProcessID,
a.sess_id as SessionID,
n.nspname as SchemaName,
c.relname as RelationName,
CASE c.relkind
WHEN 'r' THEN 'table'
WHEN 'v' THEN 'view'
WHEN 'i' THEN 'index'
WHEN 'S' THEN 'sequence'
WHEN 's' THEN 'special'
END as RelationType,
pg_catalog.pg_get_userbyid(c.relowner) as RelationOwner,
pg_size_pretty(pg_relation_size(n.nspname ||'.'|| c.relname)) as RelationSize
FROM
pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
LEFT JOIN pg_catalog.pg_stat_activity a ON 'pg_temp_' || a.sess_id::varchar = n.nspname
WHERE c.relkind IN ('r','s')
AND (n.nspname !~ '^pg_toast' and nspname like 'pg_temp%')
ORDER BY pg_relation_size(n.nspname ||'.'|| c.relname) DESC;
And you get --
processid | sessionid | schemaname | relationname | relationtype | relationowner | relationsize
-----------+-----------+------------+--------------+--------------+---------------+--------------
5006 | 9 | pg_temp_9 | tmp_a | table | gpadmin | 384 kB
5006 | 9 | pg_temp_9 | tmp_b | table | gpadmin | 384 kB
(2 rows)
Let's put that process to sleep -- and startup another....
gpadmin=#
[1]+ Stopped psql
[gpadmin#gpdb-sandbox ~]$ psql
psql (8.2.15)
Type "help" for help.
gpadmin=# SELECT nspname
FROM pg_namespace
WHERE oid = pg_my_temp_schema();
nspname
---------
(0 rows)
gpadmin=# Create temp table tmp_a( id int );
NOTICE: Table doesn't have 'DISTRIBUTED BY' clause -- Using column named 'id' as the Greenplum Database data distribution key for this table.
HINT: The 'DISTRIBUTED BY' clause determines the distribution of data. Make sure column(s) chosen are the optimal data distribution key to minimize skew.
CREATE TABLE
gpadmin=# SELECT nspname
FROM pg_namespace
WHERE oid = pg_my_temp_schema();
nspname
---------
pg_temp_10
(1 row)
... run the same query ...
processid | sessionid | schemaname | relationname | relationtype | relationowner | relationsize
-----------+-----------+------------+--------------+--------------+---------------+--------------
5006 | 9 | pg_temp_9 | tmp_a | table | gpadmin | 384 kB
5006 | 9 | pg_temp_9 | tmp_b | table | gpadmin | 384 kB
27365 | 10 | pg_temp_10 | tmp_a | table | gpadmin | 384 kB
(3 rows)

DROP TABLE on a Child table getting blocked by a SELECT on the parent table in Postgres 9.5

I have a parent/child relationship between table T and T_CHILD. When I have an Active transaction SELECTING from the parent - T, and I try to drop the child table (T_CHILD), the DROP statement just hangs, as this session tries to get an Access Exclusivelock on both the parent and child tables.
1. Is this expected behavior?
2. Why should Postgres prevent a child table from being dropped, eventhough dropping the child table has no impact on the SELECT on the parent table? Can you please explain this?
dev_sporuran=# \d+ t
Table "public.t"
Column | Type | Modifiers | Storage | Stats target | Description
--------+---------+-----------+---------+--------------+-------------
id | integer | not null | plain | |
Indexes:
"t_pkey" PRIMARY KEY, btree (id)
Referenced by:
TABLE "t_child" CONSTRAINT "t_child_fk" FOREIGN KEY (t_id) REFERENCES t(id)
dev_sporuran=# \d+ t_child
Table "public.t_child"
Column | Type | Modifiers | Storage | Stats target | Description
--------+-----------------------+-----------+----------+--------------+-------------
id | integer | | plain | |
t_id | integer | | plain | |
name | character varying(10) | | extended | |
Foreign-key constraints:
"t_child_fk" FOREIGN KEY (t_id) REFERENCES t(id)
***********26727 session starts a SELECT ********
dev_sporuran=# begin;
BEGIN
dev_sporuran=# select * from t;
id
----
(0 rows)
*****26727 gets a shared lock for the SELECT on the table and the PK******
dev_sporuran=# select locktype,database,relation::regclass,transactionid,pid,mode,granted
from pg_locks where pid in (26727,26780) order by pid;
locktype | database | relation | transactionid | pid | mode | granted
------------+----------+----------+---------------+-------+-----------------+---------
relation | 19752133 | pg_locks | | 26727 | AccessShareLock | t
relation | 19752133 | t_pkey | | 26727 | AccessShareLock | t
relation | 19752133 | t | | 26727 | AccessShareLock | t
virtualxid | | | | 26727 | ExclusiveLock | t
(4 rows)
**************26827 tries to DROP the t_child table ************
dev_sporuran=# select pg_backend_pid();
pg_backend_pid
----------------
26867
(1 row)
dev_sporuran=# drop table t_child;
********* This just hangs;
Looking at pg_locks - 26867 requires not only an Access Exclusive lock on t_child, it also needs an Access Exclusive Lock on the parent table - T.
But it cannot get it, because 26727 has a Share lock on it thru the SELECT statement. So it has to wait*****
dev_sporuran=# select locktype,virtualxid,relation::regclass,transactionid,pid,mode,granted
from pg_locks where pid in (26727,26867) and relation::regclass in ('t','t_pkey','t_child') order by pid;
locktype | virtualxid | relation | transactionid | pid | mode | granted
----------+------------+----------+---------------+-------+---------------------+---------
relation | | t_pkey | | 26727 | AccessShareLock | t
relation | | t | | 26727 | AccessShareLock | t
relation | | t_child | | 26867 | AccessExclusiveLock | t
relation | | t | | 26867 | AccessExclusiveLock | f
(4 rows)
Thanks
Murali
Seems like something you could raise for discussion on pgsql-hackers. At a glance I don't see a good reason it shouldn't be ExclusiveLock not AccessExclusiveLock, so it'd still permit SELECT. But most table structure alterations require A.E.L.
Take a look at the ALTER TABLE lock strengths reduction patch for how complex this sort of thing can be.

Does Rollback automatically end transaction in Postgres

Using PostgreSQL 9.1
In this code:
BEGIN TRANSACTION
// Do something
If error then
ROLLBACK //<--Does this automatically End Transaction
Else
COMMIT //<--Automatically Ends Transaction
End if
Is an END TRANSACTION command necessary after the ROLLBACK command?
Rollback has end Your transaction, no need another command.
Here some example :
test_general=# begin;
BEGIN
test_general=# lock TABLE t1 ;
LOCK TABLE
test_general=# select locktype, relname, mode from pg_locks l inner join pg_class c on c.oid = l.relation;
locktype | relname | mode
----------+----------------------------+---------------------
relation | pg_namespace_oid_index | AccessShareLock
relation | pg_class_relname_nsp_index | AccessShareLock
relation | t1 | AccessExclusiveLock
test_general=# rollback;
ROLLBACK
test_general=# select locktype, relname, mode from pg_locks l inner join pg_class c on c.oid = l.relation;
locktype | relname | mode
----------+----------------------------+-----------------
relation | pg_class_relname_nsp_index | AccessShareLock
relation | pg_class_oid_index | AccessShareLock
relation | pg_class | AccessShareLock
relation | pg_locks | AccessShareLock
(4 rows)
Lock released means that the transaction is over.