Re: Connection terminated but client didn't realise
> Is the application remote from the database server? My gut reaction to this > type of report is "something timed out the network connection", but there > would have to be a router or firewall or the like in between to make that a > tenable explanation. > If that is the issue, you should be able to fix it by making the server's > TCP keepalive settings more aggressive. Yes the application server is separate from the database server, and the application is running within docker which I suspect adds some complexity too. I had suspicions about something in the middle closing the connection too, but your email has clarified my thinking a bit. TCP Keepalive appears to be enabled on the application server and within docker, and the client holds the allegedly dead connection for much longer (24h) than the keepalive should take to kill it (<3h), so I think the next step is to try to identify the connection at the OS level with netstat to see what state it's in. Thanks for your help. Regards, David On 2/12/19, 11:17 pm, "Tom Lane" wrote: David Wheeler writes: > We have a query that our system runs nightly to refresh materialised views. This takes some time to execute (~25 minutes) and then it will usually return the results to the application and everything is golden. However occasionally we see something like the below, where the query finishes, but the connection gets unexpectedly closed from Postgres’ perspective. From the application’s perspective the connection is still alive, and it sits there forever waiting for the result. Is the application remote from the database server? My gut reaction to this type of report is "something timed out the network connection", but there would have to be a router or firewall or the like in between to make that a tenable explanation. If that is the issue, you should be able to fix it by making the server's TCP keepalive settings more aggressive. regards, tom lane
Permission inconsistency with views that call functions
Hi all I’m seeing some inconsistency with how permissions are enforced within views. In particular, if the view accesses a table directly, then the table is accessible, however if the view uses a function to access the table then permission is denied. Here’s a demonstration (from pg13.0) createdb temp psql temp <<\EOF create schema hidden; create table hidden.tab (col1 text); insert into hidden.tab values ('abc'); create function test() returns text[] as $$ select array_agg(col1) from hidden.tab; $$ language sql stable; create view tv1 as select test(); create view tv2 as select array_agg(col1) from hidden.tab; grant select on tv1 to public; grant select on tv2 to public; create user test password 'test' login; EOF PGPASSWORD=test psql -U test temp <<\EOF \echo select * from tv1; select * from tv1; \echo --- \echo select * from tv2; select * from tv2; set jit_inline_above_cost to -1; \echo --- \echo select * from tv1; -- no jit inlining select * from tv1; EOF OUTPUT ERROR: permission denied for schema hidden LINE 2: select array_agg(col1) from hidden.tab; ^ QUERY: select array_agg(col1) from hidden.tab; CONTEXT: SQL function "test" during inlining --- select * from tv2; array_agg --- {abc} (1 row) SET --- select * from tv1; -- no jit inlining ERROR: permission denied for schema hidden LINE 2: select array_agg(col1) from hidden.tab; ^ QUERY: select array_agg(col1) from hidden.tab; CONTEXT: SQL function "test" during inlining Is this expected/desirable? Any ideas how I can work around it, short of inlining every function manually (if that’s even possible) or granting access to the “hidden” schema? Thanks in advance! Best regards, David Wheeler, Inomial Architect E. dwhee...@dgitsystems.com<mailto:dwhee...@dgitsystems.com> 313 La Trobe Street, Victoria 3000, Australia +61 3 8820 5200 MELBOURNE . DENPASAR . AUCKLAND WWW.DGITSYSTEMS.COM<http://www.dgitsystems.com/> [signature_414257395]<https://www.dgitsystems.com/>
Re: Permission inconsistency with views that call functions
Thanks for the reply > VIEWs operate as if they were "SECURITY DEFINER". My concern is that the view is not acting as a security barrier underneath which all access is evaluated using the view owner context; in some circumstances (when the view calls a function) the access is evaluated using the caller’s context. Caller | | V - View -- Security definition layer | | (b) || (a)|v | Function (not SECURITY DEFINER or explicitly SECURITY INVOKER) || || || Vx Table I would expect that everything underneath the View would use the view owner to evaluate permissions. However it seems that in scenario (b) it enters a new security context from the caller, rather than inheriting it from the view. > The solution to your issue is possibly to make the function "SECURITY > DEFINER". This works, but I see this as a workaround, because the function is simply a utility that makes understanding the data in the table a little easier. Why should it be security definer? If you don’t have access to the table you shouldn’t be able to use the function to access it. Regards, David On 24/2/21, 2:41 am, "Joe Conway" wrote: On 2/22/21 10:32 PM, David Wheeler wrote: > I’m seeing some inconsistency with how permissions are enforced within views. > In > particular, if the view accesses a table directly, then the table is > accessible, > however if the view uses a function to access the table then permission is > denied. Without looking too closely at the details, I can almost guarantee that the issue is that FUNCTIONs default to "SECURITY INVOKER" whereas VIEWs operate as if they were "SECURITY DEFINER". See slide 33 here: http://joeconway.com/presentations/security-pgcon2020.pdf The solution to your issue is possibly to make the function "SECURITY DEFINER". I have mused previously (not sure if I ever did on the lists, but in any case) that it would be cool if VIEWs could have the option to be either DEFINER or INVOKER so that VIEWs and FUNCTIONs could be treated the same, but no efforts have been made in that direction as far as I am aware. HTH, Joe -- Crunchy Data - http://crunchydata.com PostgreSQL Support for Secure Enterprises Consulting, Training, & Open Source Development
Re: How to avoid Trigger ping/pong / infinite loop
>> Are there techniques for situations like this? Just have two triggers, one for each column, and ensure that if your trigger doesn’t change the value then it doesn’t do an update on the other column. Each time you do update both triggers will run but only one will make a change, so that will break the cycle For insert case ensure the triggers do nothing if their source col is null
IS as a binary operator
Heya folks, Recently I've been using a Kotlin library SQLDelight <https://cashapp.github.io/sqldelight/2.0.0-alpha05/> which is great but has some issues with PostgreSQL support. In particular, for null parameters it converts `=` to `IS` - and it treats `IS` as a binary operator (rather than `IS NULL` unary operator), which Postgres doesn't like wrt prepared statements prepare test(text) as (SELECT * FROM test WHERE nullable_col IS $1); ERROR: syntax error at or near "$1" LINE 1: ...epare test(text) as (SELECT * FROM test WHERE nullable_col IS $1); full details at [1] I’ve been working on a PR to use `IS NOT DISTINCT FROM` as the `=` substitution for nullable parameters rather than `IS`, however unfortunately that’s not universally supported either (MySQL). Just wondering if anyone has other ideas? I guess there’s no interest in adding support for `IS` as basically an alias for `IS NOT DISTINCT FROM`? (and `IS NOT` for `IS DISTINCT FROM`) TIA David Wheeler [1] https://github.com/cashapp/sqldelight/issues/3863
Materialized view breaks pg_restore
Hi, We’re regularly having an issue when restoring dumps of our databases like this [exec] CREATE DATABASE "testRestore"; [exec] pg_restore: [archiver (db)] Error while PROCESSING TOC: [exec] pg_restore: [archiver (db)] Error from TOC entry 15728; 0 43798 MATERIALIZED VIEW DATA fact_tax dbowner@smile-DEV_2019-03-22T09-32-13.338 [exec] pg_restore: [archiver (db)] could not execute query: ERROR: relation "basic" does not exist [exec] LINE 1: SELECT chargegst from basic where uid = _account [exec] ^ [exec] QUERY: SELECT chargegst from basic where uid = _account [exec] CONTEXT: PL/pgSQL function ar.categorise_gst(integer,integer,date) line 7 at IF [exec] Command was: REFRESH MATERIALIZED VIEW cube02.fact_tax; The issue is that there’s a mat view that refers to a plpgsql function that refers to a table in the public schema, but it’s not qualified. When we create the materialized view, and when we refresh it, the table is in the search path. But when restoring from a dump, it’s not. Is this the desired behaviour? This is an issue for us because pg_dump/pg_restore is part of our disaster recovery process, so if we find this problem during restore it will mean more downtime. PG version 9.5.14. I’m attempting to find out now if it’s an issue in more recent versions also. TIA David Wheeler Software developer [cid:2C4D0888-9F8B-463F-BD54-2B60A322210C] E dwhee...@dgitsystems.com<mailto:dwhee...@dgitsystems.com> D +61 3 9663 3554 W http://dgitsystems.com Level 4, 313 La Trobe St, Melbourne VIC 3000.
Re: what happens if a failed transaction is not rolled back?
> On 25 Apr 2023, at 1:47 am, David G. Johnston > wrote: > > There isn't anything special about a failed transaction compared to any other > transaction that you leave open. Now I’m curious. Does it have the same impact on performance that an idle in transaction connection has? Eg does it prevent vacuum? Does it still hold locks? David
Re: Return rows in input array's order?
> Hi. With an integer identity primary key table, > we fetch a number of rows with WHERE id = ANY($1), > with $1 an int[] array. The API using that query must return > rows in the input int[] array order, and uses a client-side > mapping to achieve that currently. > > Is it possible to maintain $1's order directly in SQL? Efficiently? We’ve done this before with an “order by array_index(id, input_array)”. I forget the actual function consider that pseudo code It was only used for small arrays but never noticed any performance issues
Re: Return rows in input array's order?
>> It was only used for small arrays but never noticed any performance issues > > Hmmm, sounds like this would be quadratic though... True, but it’s cpu time not io, which tends to be orders of magnitude slower > I wonder whether the int[] can be turned into a pseudo table with a ROWNUM > extra generated column that > would then be (LEFT) JOIN'd to the accessed table, so that the original array > index is readily accessible. > Would something like this be possible in Postgres' SQL? The unnest function mentioned above has a “with ordinality” option which gives easy access to the array index so a simple join would do the trick
Deadlock with 2 processes waiting on transactionids and locking unrelated tables
---+--- relation || | 56/2306861 | 41715 | RowExclusiveLock | planscheduleitem_plan_company_idx| | relation || | 56/2306861 | 41715 | RowExclusiveLock | psi_uid_startdate| | relation || | 56/2306861 | 41715 | RowExclusiveLock | psi_planschedule_startdate_starttime | | relation || | 56/2306861 | 41715 | RowExclusiveLock | planscheduleitem_pkey| | relation || | 56/2306861 | 41715 | RowExclusiveLock | planscheduleitem | | virtualxid| 56/2306861 | | 56/2306861 | 41715 | ExclusiveLock| | | transactionid ||4089783283 | 56/2306861 | 41715 | ExclusiveLock| | | (7 rows) TIA Cheers, -- David <http://www.inomial.com/> <http://www.inomial.com/>David Wheeler • software engineer Inomial Pty Ltd • Automatic Billing <http://www.inomial.com/> p +61 3 9663 3554 <http://www.linkedin.com/company/inomial-pty-ltd> <https://www.facebook.com/Inomial> <https://twitter.com/inomial> <https://twitter.com/inomial>
Re: Deadlock with 2 processes waiting on transactionids and locking unrelated tables
Thanks for your response > Does any of the two tables have triggers? Yes the ticket table has a trigger that inserts changes into a ticketstatuslog table when the ticket.status column changes and on insert. ticket_status_insert_trigger AFTER INSERT ON ticket FOR EACH ROW EXECUTE PROCEDURE ticket_status_trigger_function() ticket_status_update_trigger AFTER UPDATE OF ticketstatus ON ticket FOR EACH ROW WHEN (old.ticketstatus <> new.ticketstatus) EXECUTE PROCEDURE ticket_status_trigger_function() > What's the database / transaction isolation level? Both read committed > Do the updates run in a transaction among other read / write operations > within the same transaction ? Yes they will both have many reads and writes before running the deadlocking query. Cheers, -- David <http://www.inomial.com/> <http://www.inomial.com/>David Wheeler • software engineer Inomial Pty Ltd • Automatic Billing <http://www.inomial.com/> p +61 3 9663 3554 <http://www.linkedin.com/company/inomial-pty-ltd> <https://www.facebook.com/Inomial> <https://twitter.com/inomial> <https://twitter.com/inomial> > On 19 Feb 2018, at 4:43 pm, Rene Romero Benavides > wrote: > > Hi. Does any of the two tables have triggers? What's the database / > transaction isolation level? Do the updates run in a transaction among other > read / write operations within the same transaction ? > Regards. > > 2018-02-18 23:28 GMT-06:00 David Wheeler <mailto:da...@inomial.com>>: > Hi, > > We’re seeing deadlock semi-regularly (0-2 per day) that I’m really having > trouble getting to the bottom of. > > Process 7172 waits for ShareLock on transaction 4078724272 > ; blocked by process 7186. > Process 7186 waits for ShareLock on transaction 4078724210 > ; blocked by process 7172. > > The two queries in question are updates on unrelated tables. Running the > queries on their own shows no overlapping entries in pg_locks. > > Process 7172: update ticket set unread = true where ticketid = $1 > Process 7186: update "planscheduleitem" set "planschedule"=$1 where "psi"=$2 > > How can I work out why Postgres has decided that the two processes are in > deadlock? Is there an explainer somewhere on transaction level locks? I can’t > see anything in the docs besides that they exist. > > > > Details below > > select version(); > version > --- > PostgreSQL 10.2 (Ubuntu 10.2-1.pgdg14.04+1) on x86_64-pc-linux-gnu, compiled > by gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4, 64-bit > (1 row) > > --- > > > after running update "planscheduleitem" set "planschedule"=$1 where "psi"=$2 > > SELECT locktype, virtualxid, transactionid, virtualtransaction, pid, mode, > relname, page, tuple > FROM pg_locks LEFT JOIN pg_class ON (relation=oid) where pid =41715; >locktype| virtualxid | transactionid | virtualtransaction | pid | >mode | relname | page | tuple > ---++---++---+--+-+--+--- > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_parentticketid | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_originalticketid | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_tickettypeid_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_subject_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_closedtime_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_assignedto_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_serviceuid_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_parentuid_idx| | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_createdtime_idx | | > relation || | 56/2306863
Re: Deadlock with 2 processes waiting on transactionids and locking unrelated tables
Oh I see. Yeah it’s kind of obvious now that you point it out! > Btw, do the transactions use explicit locking? We occasionally use for update so that could be involved. We’ll have a closer look at the code involved. I’m still curious about why the locks are both transaction locks rather than one of them being a row lock. Thanks for your help! Cheers, -- David <http://www.inomial.com/> <http://www.inomial.com/>David Wheeler • software engineer Inomial Pty Ltd • Automatic Billing <http://www.inomial.com/> p +61 3 9663 3554 <http://www.linkedin.com/company/inomial-pty-ltd> <https://www.facebook.com/Inomial> <https://twitter.com/inomial> <https://twitter.com/inomial> > On 19 Feb 2018, at 5:54 pm, Rene Romero Benavides > wrote: > > My guess is that the transaction doing: > > update "planscheduleitem" set "planschedule"=$1 where "psi"=$2 > > updates ticket before reaching that point > > And > > update ticket set unread = true where ticketid = $1 > > updates planscheduleitem before that > > Does it make sense to you? Btw, do the transactions use explicit locking? > > 2018-02-18 23:28 GMT-06:00 David Wheeler <mailto:da...@inomial.com>>: > Hi, > > We’re seeing deadlock semi-regularly (0-2 per day) that I’m really having > trouble getting to the bottom of. > > Process 7172 waits for ShareLock on transaction 4078724272 > ; blocked by process 7186. > Process 7186 waits for ShareLock on transaction 4078724210 > ; blocked by process 7172. > > The two queries in question are updates on unrelated tables. Running the > queries on their own shows no overlapping entries in pg_locks. > > Process 7172: update ticket set unread = true where ticketid = $1 > Process 7186: update "planscheduleitem" set "planschedule"=$1 where "psi"=$2 > > How can I work out why Postgres has decided that the two processes are in > deadlock? Is there an explainer somewhere on transaction level locks? I can’t > see anything in the docs besides that they exist. > > > > Details below > > select version(); > version > --- > PostgreSQL 10.2 (Ubuntu 10.2-1.pgdg14.04+1) on x86_64-pc-linux-gnu, compiled > by gcc (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4, 64-bit > (1 row) > > --- > > > after running update "planscheduleitem" set "planschedule"=$1 where "psi"=$2 > > SELECT locktype, virtualxid, transactionid, virtualtransaction, pid, mode, > relname, page, tuple > FROM pg_locks LEFT JOIN pg_class ON (relation=oid) where pid =41715; >locktype| virtualxid | transactionid | virtualtransaction | pid | >mode | relname | page | tuple > ---++---++---+--+-+--+--- > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_parentticketid | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_originalticketid | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_tickettypeid_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_subject_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_closedtime_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_assignedto_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_serviceuid_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_parentuid_idx| | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_createdtime_idx | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_txid | | > relation || | 56/2306863 | 41715 | > RowExclusiveLock | ticket_tickettype | | > relation || | 56/2306863