Wouldn't it be easier just to prevent connections to the database
 while your transaction is executed?
EG:
<Connect to your_database>
UPDATE pg_database
  SET datallowconn FALSE
 WHERE datname = 'your_database' ;
 START TRANSACTION;
<Do your_transaction>
  COMMIT;
UPDATE pg_database
  SET datallowconn TRUE
 WHERE datname = 'your_database' ;


On Fri, Jul 3, 2015 at 1:25 PM, Filipe Pina <filipe.p...@impactzero.pt>
wrote:

> So, as database level locks do not exist (as per
> https://wiki.postgresql.org/wiki/Lock_database), I've thought of having a
> function that would lock *every* table in the database (far from the same,
> but would probably work for me).
>
> Something like:
>
> CREATE OR REPLACE FUNCTION lockdown()
>     RETURNS void AS $$
> DECLARE
>   t information_schema.tables.table_name%TYPE;
> BEGIN
>   FOR t in SELECT table_name
>     FROM information_schema.tables
>   WHERE table_schema='public'
>    AND table_type='BASE TABLE'
>   LOOP
>     EXECUTE 'LOCK ' || t;
>   END LOOP;
> END
> $$
> LANGUAGE plpgsql;
>
> But the problem is that calling the function starts its own transaction
> and once it returns, locks are removed..
>
> Basically the workflow is (pseudo code coming from
> Django/python/psycopg2/external, not within pgsql):
>
> function generic_function_restarter(developer_function) {
>   # try 4 times to execute developer function and if all of them fail
>   # (due to SQLSTATE 40001 serialization failures),
>   # lock database and execute one last time
>   for 1 in [1..4] {
>     try {
>       call developer_function()
>       return 'success'
>     }
>     except SQLSTATE_40001 {
>       continue
>     }
>     except other_error {
>       return other_error
>     }
>
>   # only reaches here if all tries failed with SQLSTATE_40001
>   try {
>     START TRANSACTION
>     call lockdown()
>     call developer_function()
>     COMMIT TRANSACTION
>     return 'success'
>   }
>   except any_error {
>     # implicit ROLLBACK
>     return any_error
>   }
> }
>
> So, my problem here is that "call lockdown()" will place the locks and
> remove them upon returning... Is it possible to execute a function without
> creating a subtransaction?
>
> I could place the locks from the adapter directly at the outter
> transaction level but I have the feeling that performance would be worse...
>
> Thanks,
> Filipe
>
> On Sex, Jun 12, 2015 at 5:25 , Filipe Pina <filipe.p...@impactzero.pt>
> wrote:
>
> Exactly, that’s why there’s a limit on the retry number. On the last try I
> wanted something like full lockdown to make sure the transaction will not
> fail due to serialiazation failure (if no other processes are touching the
> database, it can’t happen). So if two transactions were retrying over and
> over, the first one to reach max_retries would activate that “global lock”
> making the other one wait and then the second one would also be able to
> successfully commit...
>
> On 11/06/2015, at 20:27, Tom Lane <t...@sss.pgh.pa.us> wrote: Filipe Pina <
> filipe.p...@impactzero.pt> writes:
>
> It will try 5 times to execute each instruction (in case of
> OperationError) and in the last one it will raise the last error it
> received, aborting.
>
>  Now my problem is that aborting for the last try (on a restartable error
> - OperationalError code 40001) is not an option... It simply needs to get
> through, locking whatever other processes and queries it needs.
>
> I think you need to reconsider your objectives. What if two or more
> transactions are repeatedly failing and retrying, perhaps because they
> conflict? They can't all forcibly win. regards, tom lane
>
>


-- 
*Melvin Davidson*
I reserve the right to fantasize.  Whether or not you
wish to share my fantasy is entirely up to you.

Reply via email to