zoukankan      html  css  js  c++  java
  • Rolling back a transaction within a plpgsql function?

    postgresql在function不能用start transaction, commit 或rollback
    因为它已经设定:所有的function里的语句只能含在一个transaction之中。也必然在一个transaction之中。
    它是含在调用function语句的transaction之中。
    所以不用写start transaction 就能满足你的要求

    ===================================

    from:

    http://stackoverflow.com/questions/2422205/postgresql-rolling-back-a-transaction-within-a-plpgsql-function

    Coming from the MS SQL world, I tend to make heavy use of stored procedures. I'm currently writing an application uses a lot of PostgreSQL plpgsql functions. What I'd like to do is rollback all INSERTS/UPDATES contained within a particular function if I get an exception at any point within it.
    I was originally under the impression that each function is wrapped in it's own transaction and that an exception would automatically rollback everything. However, that doesn't seem to be the case. I'm wondering if I ought to be using savepoints in combination with exception handling instead? But I don't really understand the difference between a transaction and a savepoint to know if this is the best approach. Any advice please?

    CREATE OR REPLACE FUNCTION do_something(
             _an_input_var int
                    ) RETURNS bool AS $$
            DECLARE
                    _a_variable int;
            BEGIN
                    INSERT INTO tableA (col1, col2, col3)
                            VALUES (0, 1, 2);

                    INSERT INTO tableB (col1, col2, col3)
                            VALUES (0, 1, 'whoops! not an integer');

                    -- The exception will cause the function to bomb, but the values
                    -- inserted into "tableA" are not rolled back. (不可能的!一定是其他原因。)  

                    RETURN True;
    END; $$ LANGUAGE plpgsql;

    ===================================

    Can you post an example of a function that doesn't rollback everything as you would expect? PL/pgSQL functions do execute within the transaction context of the calling statement, but a BEGIN..EXCEPTION block can modify that behavior. Without seeing an example, it's hard to give the proper advice. – Matthew Wood Mar 11 '10 at 18:19
        
    Edited to add an example. Thanks. – jamieb Mar 11 '10 at 18:33
        
    I'm running 8.4.2, created tableA and B with three int columns each, run your example (with ";" removed at the end of INSERT INTO tableB line) and it bombed. I checked both tables and they were both empty. I even added some debug code between the two to verify that the record was there before it failed, then it was gone after the failure. – Matthew Wood Mar 11 '10 at 19:00
        
    Each function will be in it's own transaction, it's impossible with the current example to add a new record in tableA and have an error on tableB. No way this will happen, impossible. And you don't need savepoints as mentioned, just do some propper testing and see how things are working. In PostgreSQL, everything is about data integrity, you don't have to worry about that. – Frank Heikens Mar 11 '10 at 19:07
        
    Matthew -- You're correct. I overly reduced the complexity of my code snippet and in doing so, eliminated the apparent problem. I will continue to test it to try and locate the problem. Thanks for your time and assistance. – jamieb Mar 11 '10 at 20:56
     

    That is not true for PostgreSQL. A single SQL statement, when not executed as a part of explicit transaction (is not executed between BEGIN and COMMIT/END), is executed as a single transaction. But if such statement calls multiple functions, then all the functions are executed in one transaction. Also, when you have multiple statement transaction (explicit BEGIN, COMMIT) and those statements call some procedures, all of those will be executed in the single transactions. As others have said: savepoints are the way to go. – Jacek Konieczny

    ===================================

    @Jacek: Joshua is right, a function does represent it's own transaction. You don't need a savepoint to rollback both inserts, if one fails, they both will fail. – Frank Heikens Mar 11 '10 at 19:08
    1     
        
    @Frank: But that is because of the outer transaction. The inserts in other function called in the same statement or previous statements in the transaction will also fail. And you cannot rollback the inserts from the function without rolling back other results of the outer transaction, unless you use the savepoints. Function body is always executed within a transaction, but it is not a transaction by itself. There is just no way to call a function not starting a transaction. – Jacek Konieczny Mar 12 '10 at 7:30
    ===================================

    The docs say this:
        A savepoint is a special mark inside a transaction that allows all commands that are executed after it was established to be rolled back, restoring the transaction state to what it was at the time of the savepoint.

    They give examples too.

    Edit:

    You need to wrap a transaction in BEGIN and COMMIT commands.

        a transaction is set up by surrounding the SQL commands of the transaction with BEGIN and COMMIT commands

    link|improve this answer
        
    edited Mar 11 '10 at 23:55

        
    answered Mar 11 '10 at 3:01
    tom
    365110
        
        
    I disagree that the docs are clear. The description of a "savepoint" sounds exactly what I know a "transaction" to be. Are savepoints atomic? – jamieb Mar 11 '10 at 17:56
        
    As I understand it, they're just markers in a transaction that you can roll back to. The whole transaction is atomic; until it's committed no change is visible to any other transaction. – tom Mar 11 '10 at 23:58
    feedback
    up vote 0 down vote
        

    Savepoints can be used to emulate nested transactions. Because a postgresql transaction is a sequence of statements that will either be applied or discarded, savepoints can mark points within that sequence that allow rolling back to.

    Since true nested transactions are not supported, this is your best bet (and a good one at that).
     

  • 相关阅读:
    Tomcat 配置和springframework MVC配置简介
    Java监控工具、调优、调试辅助函数
    发布一个 Linux 下的 C++ 多线程库
    《程序中的日期与时间》第一章 日期计算
    《多线程服务器的适用场合》例释与答疑
    Muduo 网络编程示例之零:前言
    muduo 与 boost asio 吞吐量对比
    Muduo 网络编程示例之二:Boost.Asio 的聊天服务器
    计算机图书赠送
    muduo 与 libevent2 吞吐量对比
  • 原文地址:https://www.cnblogs.com/luoyaoquan/p/2140591.html
Copyright © 2011-2022 走看看