查询并触发事务内的执行顺序
Queries and triggers execution order inside transaction
如果在事务内部调用了触发器,是否保证所有触发器(non-constraint/non-deferred 触发器)都将在事务中的下一个查询开始之前完成。
例如我有以下 table:
Table a
id name is_updated
1 alice False
2 alice False
3 Alice False
在此 table 上定义触发器之前的行级别,如果已更新名称字段,则将 is_updated 设置为 True。
我执行以下交易:
BEGIN;
UPDATE table_a SET name = 'Alice' WHERE name = 'alice';
UPDATE table_a SET is_updated = False WHERE is_updated = True;
COMMIT;
会不会是在所有触发器完成之前就开始了第二个 UPDATE 语句?或者在事务内部触发 运行 with 调用触发器的语句?
UPD1
Postgresql 版本为 9.3。
这里是触发器和相关函数源:
CREATE TRIGGER a_name_update_trigger
BEFORE UPDATE OF name
FOR EACH ROW
EXECUTE PROCEDURE on_a_name_update();
CREATE OR REPLACE FUNCTION on_a_name_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.is_updated = True;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
没什么不对,除了我认为触发器的定义应该是这样的:
CREATE OR REPLACE FUNCTION on_a_name_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.is_updated = true;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER a_name_update_trigger
BEFORE update of name ON table_a
FOR EACH ROW
EXECUTE PROCEDURE on_a_name_update();
因此,通过执行您的查询:
BEGIN;
UPDATE table_a SET name = 'Alice' WHERE name = 'alice';
UPDATE table_a SET is_updated = False WHERE is_updated = True;
COMMIT;
最终更新符合预期:
id name is_updated
1 "Alice" False
2 "Alice" False
3 "Alice" False
换句话说,第二次更新是在行触发触发器后执行的(如果更新了列名)
如果在事务内部调用了触发器,是否保证所有触发器(non-constraint/non-deferred 触发器)都将在事务中的下一个查询开始之前完成。 例如我有以下 table:
Table a
id name is_updated
1 alice False
2 alice False
3 Alice False
在此 table 上定义触发器之前的行级别,如果已更新名称字段,则将 is_updated 设置为 True。
我执行以下交易:
BEGIN;
UPDATE table_a SET name = 'Alice' WHERE name = 'alice';
UPDATE table_a SET is_updated = False WHERE is_updated = True;
COMMIT;
会不会是在所有触发器完成之前就开始了第二个 UPDATE 语句?或者在事务内部触发 运行 with 调用触发器的语句?
UPD1
Postgresql 版本为 9.3。 这里是触发器和相关函数源:
CREATE TRIGGER a_name_update_trigger
BEFORE UPDATE OF name
FOR EACH ROW
EXECUTE PROCEDURE on_a_name_update();
CREATE OR REPLACE FUNCTION on_a_name_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.is_updated = True;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
没什么不对,除了我认为触发器的定义应该是这样的:
CREATE OR REPLACE FUNCTION on_a_name_update()
RETURNS TRIGGER AS $$
BEGIN
NEW.is_updated = true;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER a_name_update_trigger
BEFORE update of name ON table_a
FOR EACH ROW
EXECUTE PROCEDURE on_a_name_update();
因此,通过执行您的查询:
BEGIN;
UPDATE table_a SET name = 'Alice' WHERE name = 'alice';
UPDATE table_a SET is_updated = False WHERE is_updated = True;
COMMIT;
最终更新符合预期:
id name is_updated
1 "Alice" False
2 "Alice" False
3 "Alice" False
换句话说,第二次更新是在行触发触发器后执行的(如果更新了列名)