Using functions and transactions

As you know, everything that PostgreSQL exposes in user land is a transaction. The same, of course, applies if you are writing functions. A function is always part of the transaction you are in. It is not autonomous, just like an operator or any other operation.

Here is an example:

test=# SELECT now(), mysum(id, id) FROM generate_series(1, 3) AS id;
now | mysum -------------------------------+------- 2017-10-12 15:54:32.287027+01 | 2 2017-10-12 15:54:32.287027+01 | 4 2017-10-12 15:54:32.287027+01 | 6 (3 rows)

All three function calls happen in the same transaction. This is important to understand because it implies that you cannot do too much transactional flow control inside a function. What happens when the second function call commits? It just cannot work.

However, Oracle has a mechanism that allows for autonomous transactions. The idea is that even if a transaction rolls back, some parts might still be needed, and they should be kept. A classic example is as follows:

  1. Start a function to look up secret data.
  2. Add a log line to the document to state that somebody has modified this important secret data.
  3. Commit the log line but roll back the change.
  4. Preserve the information, stating that an attempt has been made to change data.

To solve problems such as this one, autonomous transactions can be used. The idea is to be able to commit a transaction inside the main transaction independently. In this case, the entry in the log table will prevail, while the change will be rolled back.

As of PostgreSQL 11.0, autonomous transactions are not implemented. However, there are already patches floating around that implement this feature. It is still to be seen as to when these features will make it to the core.

To give you an impression of how things will most likely work, here is a code snippet, based on the first patches:

... 
AS  
$$  
DECLARE 
  PRAGMA AUTONOMOUS_TRANSACTION;  
BEGIN 
  FOR i IN 0..9  LOOP  
    START  TRANSACTION; 
    INSERT INTO  test1  VALUES (i);  
    IF i % 2 = 0 THEN 
      COMMIT;  
    ELSE 
      ROLLBACK;  
    END IF; 
  END LOOP; 
  RETURN 42;  
END; 
$$; 
... 

The point of this example is to show you that we can decide whether to commit or to roll back the autonomous transaction on the fly.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset