2012-10-08 32 views
48

Có phải chức năng PostgreSQL như giao dịch tự động sau đây không?Các hàm PostgreSQL có giao dịch không?

CREATE OR REPLACE FUNCTION refresh_materialized_view(name) 
    RETURNS integer AS 
$BODY$ 
DECLARE 
    _table_name ALIAS FOR $1; 
    _entry materialized_views%ROWTYPE; 
    _result INT; 
BEGIN   

    EXECUTE 'TRUNCATE TABLE ' || _table_name; 

    UPDATE materialized_views 
    SET last_refresh = CURRENT_TIMESTAMP 
    WHERE table_name = _table_name; 

    RETURN 1; 
END 
$BODY$ 
    LANGUAGE plpgsql VOLATILE SECURITY DEFINER; 


Nói cách khác, nếu một lỗi xảy ra trong quá trình thực hiện các chức năng, sẽ bất kỳ thay đổi được cuộn lại? Nếu đây không phải là hành vi mặc định, làm cách nào tôi có thể thực hiện chức năng giao dịch?

+4

Tại sao bạn không tự mình kiểm tra điều này? Chỉ cần làm một ROLLBACK và bạn biết câu trả lời là gì. Nó phải là "có". –

+8

@ FrankHeikens câu hỏi của tôi là "sẽ thay đổi được tự động cuộn lại sau một lỗi", thay vì "sẽ thay đổi được cuộn lại nếu tôi thực thi ROLLBACK" –

+2

@Don Hãy nhận biết rằng 'TRUNCATE' có, hoặc đã từng có, một số hành vi giao dịch hơi sôi nổi. Tôi không nhớ những chi tiết cụ thể; tìm kiếm kho lưu trữ pgsql-general. –

Trả lời

52

Các chức năng là một phần của giao dịch mà chúng được gọi. Hiệu ứng của chúng được cuộn lại nếu giao dịch quay trở lại. Công việc của họ cam kết nếu giao dịch cam kết. Mọi khối BEGIN ... EXCEPT trong hàm hoạt động như (và dưới mui xe sử dụng) các điểm lưu trữ như các câu lệnh SQL SAVEPOINTROLLBACK TO SAVEPOINT SQL.

Chức năng hoặc thành công toàn bộ hoặc thất bại trong toàn bộ, chặn xử lý lỗi BEGIN ... EXCEPT. Nếu lỗi được nâng lên trong hàm và không được xử lý, giao dịch gọi hàm bị hủy bỏ. Các giao dịch bị hủy bỏ không thể cam kết, và nếu họ cố gắng cam kết COMMIT được coi là ROLLBACK, giống như đối với bất kỳ giao dịch nào khác do lỗi. Quan sát:

regress=# BEGIN; 
BEGIN 
regress=# SELECT 1/0; 
ERROR: division by zero 
regress=# COMMIT; 
ROLLBACK 

Xem cách giao dịch, mà là ở tình trạng lỗi do bộ phận không, cuộn lại trên COMMIT?

Nếu bạn gọi một chức năng mà không có một giao dịch surounding rõ ràng các quy định là chính xác giống như đối với bất kỳ tuyên bố Thạc khác:

BEGIN; 
SELECT refresh_materialized_view(name); 
COMMIT; 

(nơi COMMIT sẽ thất bại nếu SELECT nhướn lỗi).

PostgreSQL chưa hỗ trợ giao dịch tự động trong các hàm, trong đó thủ tục/chức năng có thể cam kết/rollback độc lập với giao dịch gọi điện. Điều này có thể được mô phỏng bằng cách sử dụng phiên mới qua dblink.

+1

Giải thích rất rõ ràng. Cảm ơn đặc biệt để minh họa câu trả lời của bạn với các ví dụ ngắn và về điểm. – informatik01

17

Theo kiến ​​thức của tôi về PostgreSQL ít sâu hơn Craig Ringer, tôi sẽ cố gắng đưa ra một câu trả lời ngắn hơn: Có.

Nếu bạn thực hiện một hàm có lỗi trong đó, không có bước nào trong số các bước sẽ tác động trong cơ sở dữ liệu.

Ngoài ra, nếu bạn thực hiện truy vấn trong PgAdmin điều tương tự.

Ví dụ, nếu bạn thực hiện trong một truy vấn:

update your_table yt set column1 = 10 where yt.id=20; 

select anything_that_do_not_exists; 

Bản cập nhật trong dòng, id = 20 của your_table sẽ không được lưu trong cơ sở dữ liệu.

+0

Cảm ơn bạn đã trả lời rõ ràng! Sau khi đọc câu trả lời của Craig, tôi đã cảm thấy không chắc chắn. – stone

+0

câu trả lời tốt hơn nhiều so với Craig's – Nulik

3

Ở cấp chức năng, nó không phải là xuyên quốc gia. Nói cách khác, mỗi câu lệnh trong hàm thuộc về một giao dịch duy nhất, là giá trị cam kết tự động mặc định của db. Tự động cam kết là đúng theo mặc định. Nhưng dù sao, bạn phải gọi hàm sử dụng

select schemaName.functionName()

Những tuyên bố trên 'chọn schemaName.functionName() 'là một giao dịch đơn lẻ, hãy đặt tên cho giao dịch T1 và do đó tất cả các câu lệnh trong hàm thuộc về giao dịch T1. Theo cách này, hàm này nằm trong một giao dịch duy nhất.

0

https://www.postgresql.org/docs/current/static/plpgsql-structure.html

Điều quan trọng là không để nhầm lẫn giữa việc sử dụng BEGIN/END cho nhóm báo cáo trong PL/pgSQL với tên tương tự câu lệnh SQL để kiểm soát giao dịch. BEGIN/END của PL/pgSQL chỉ dành cho nhóm; chúng không bắt đầu hoặc kết thúc một giao dịch. Các hàm và các thủ tục kích hoạt luôn được thực hiện trong một giao dịch được thiết lập bởi truy vấn bên ngoài - chúng không thể khởi động hoặc giao dịch được, vì sẽ không có ngữ cảnh nào để chúng thực thi. Tuy nhiên, một khối có chứa một mệnh đề EXCEPTION có thể tạo thành một subtransaction có thể được cuộn lại mà không ảnh hưởng đến giao dịch bên ngoài. Để biết thêm về điều đó, xem Phần 39.6.6.

Các vấn đề liên quan