希望是一个简单的问题,但我还没有找到一个像样的答案.我被可靠地告知,PostgreSQL(特别是9.0.4版)中的存储过程(用户定义的DB函数)本质上是事务性的,因为它们是通过SELECT语句调用的,SELECT语句本身就是事务.那么,如何 Select 存储过程的隔离级别呢?我相信在其他DBMS中,所需的事务块将被包装在一个启动事务块中,所需的隔离级别是一个可选参数.
作为一个具体的虚构例子,我想这样做:
CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS
$$
BEGIN
INSERT INTO data_table VALUES (rowtext);
UPDATE row_counts_table SET count=count+1;
END;
$$
LANGUAGE plpgsql
SECURITY DEFINER;
想象一下,我想确保这个函数始终作为可序列化事务执行(是的,是的,PostgreSQL serializable不是适当的可序列化事务,但这不是重点).我不想要求它被称为
START TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SELECT add_new_row('foo');
COMMIT;
那么,我如何将所需的隔离级别下推到函数中呢?我相信我不能在BEGIN
声明中只把隔离级别设为the manual says
重要的是不要混淆用法
对我来说,最明显的方法是在函数定义的某个地方使用SET TRANSACTION
,例如:
CREATE FUNCTION add_new_row(rowtext TEXT)
RETURNS VOID AS
$$
BEGIN
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
INSERT INTO data_table VALUES (rowtext);
UPDATE row_counts_table SET count=count+1;
END;
$$
LANGUAGE plpgsql
SECURITY DEFINER;
虽然这是可以接受的,但不清楚我能否依靠它来工作.SET TRANSACTION
的documentation表示
如果执行SET事务时没有
这让我感到困惑,因为如果我调用一个单独的SELECT add_new_row('foo');
语句(前提是我没有禁用autocommit),我希望SELECT以会话默认隔离级别的单行事务运行.
manual人还说:
无法设置事务隔离级别
那么,如果从隔离级别较低的事务中调用函数,会发生什么情况,例如:
START TRANSACTION ISOLATION LEVEL READ COMMITTED;
UPDATE row_counts_table SET count=0;
SELECT add_new_row('foo');
COMMIT;
还有一个额外的问题:函数的语言有什么不同吗?PL/pgSQL中的隔离级别设置会与普通SQL中的不同吗?
我是标准和记录在案的最佳实践的粉丝,所以任何像样的参考都将不胜感激.