- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
更新:我从问题中排除了 Hibernate。我完全修改了问题描述以尽可能简化它。
我有带 noop 触发器的 master
表和 detail
表,master
和 detail
表之间有两种关系:
create table detail (
id bigint not null,
code varchar(255) not null,
primary key (id)
);
create table master (
id bigint not null,
name varchar(255),
detail_id bigint, -- "preferred" detail is one-to-one relation
primary key (id),
unique (detail_id),
foreign key (detail_id) references detail(id)
);
create table detail_candidate ( -- "candidate" details = many-to-many relation modeled as join table
master_id bigint not null,
detail_id bigint not null,
primary key (master_id, detail_id),
foreign key (detail_id) references detail(id),
foreign key (master_id) references master(id)
);
create or replace function trgf() returns trigger as $$
begin
return NEW;
end;
$$ language 'plpgsql';
create trigger trg
before insert or update
on master
for each row execute procedure trgf();
insert into master (id, name) values (1000, 'x'); -- this is part of database setup
insert into detail (code, id) values ('a', 1); -- this is part of database setup
在这样的设置中,我使用 psql
打开两个终端窗口并执行以下步骤:
begin;
update master set detail_id=null, name='y' where id=1000;
begin;
set statement_timeout = 4000;
insert into detail_candidate (master_id, detail_id) values (1000, 1);
第二个终端中的最后一个命令超时消息
ERROR: canceling statement due to statement timeout
CONTEXT: while locking tuple (0,1) in relation "master"
SQL statement "SELECT 1 FROM ONLY "public"."master" x WHERE "id" OPERATOR(pg_catalog.=) $1 FOR KEY SHARE OF x"
我的观察和问题(变化是独立的):
drop trigger trg on master;
在初始设置后调用,一切正常。为什么 noop 触发器的存在会产生这样的影响?我不明白。master.detail_id
没有唯一约束(即 alter table master drop constraint master_detail_id_key;
在初始设置后调用),一切正常也很好。为什么?detail=null
赋值时(因为无论如何设置中都有 null 值),一切也都正常。为什么?在 Postgres 9.6.12(嵌入式)、9.6.15(在 Docker 中)、11.5(在 Docker 中)上尝试过。
问题在 Docker 镜像 tomaszalusky/trig-example
中重现,它在 DockerHub 上可用或可以从 this Dockerfile 构建(里面的说明)。
更新 2: 我发现了以上三个观察结果的共同行为。我生成了查询 select * from pgrowlocks('master')
from pgrowlocks extension在第二次交易中。 row-level lock master
中的更新行在失败情况下是FOR UPDATE
,但在所有三种工作情况下都是FOR NO KEY UPDATE
。这完全符合 mode match table in documentation因为 FOR UPDATE
模式更强,插入语句请求的模式是 FOR KEY SHARE
(从错误消息中可以明显看出,还调用了 select ... for key share
命令与 insert
命令具有相同的效果。
FOR UPDATE
模式的文档说:
The FOR UPDATE lock mode is also acquired by (...) an UPDATE that modifies the values on certain columns. Currently, the set of columns considered for the UPDATE case are those that have a unique index on them that can be used in a foreign key (...)
master.detail_id
列为真。然而,仍然不清楚为什么 FOR UPDATE
模式不是根据触发器的存在而独立选择的,以及为什么触发器的存在会导致它。
最佳答案
有趣的问题。这是我最好的猜测。我没有测试过。
一般来说,postgres 对语句将对数据产生什么影响的有根据的猜测不会扩展到触发器逻辑中。当执行第二条语句时,postgres 看到了外键约束,并且知道它必须检查分配(插入)的值是否有效,也就是说,它是否代表外表中的有效键。触发器可能会影响所提议的外键的有效性(例如,如果触发器删除记录),但这种做法可能会很糟糕。
(情况 1)如果没有触发器,则它可以查看数据(预提交和准备提交的数据)并确定建议的值是否保证有效。 (case 2) 如果没有 FK 约束,则触发器不会影响插入的有效性,因此是允许的。 (案例 3)如果您省略 detail_id=null
,则更新中没有任何变化,因此触发器不会触发,因此它的存在是无关紧要的。
我尽量避免 FK 约束和触发器。在我看来,最好是让数据库不小心包含部分不正确的数据,然后让它完全挂起,就像您在这里看到的那样。我会放弃所有 FK 约束和触发器,并强制所有更新和插入操作通过存储函数进行操作,这些函数在开始/提交锁内执行验证,并立即适本地处理不正确/无效的插入/更新尝试,而不是强制 postgres在决定是否允许命令 2 之前等待命令 1 提交。
编辑:参见this question
编辑 2: 我能找到的关于触发器时间与约束检查最接近的官方文档来自 triggers docs。
The trigger can be specified to fire before the operation is attempted on a row (before constraints are checked and the INSERT, UPDATE, or DELETE is attempted); or after the operation has completed (after constraints are checked and the INSERT, UPDATE, or DELETE has completed); or instead of the operation (in the case of inserts, updates or deletes on a view). If the trigger fires before or instead of the event, the trigger can skip the operation for the current row, or change the row being inserted (for INSERT and UPDATE operations only).
这个有点不清楚,约束检查前发生的触发是否适用于其他事务的约束检查。不管怎样,这个问题要么是一个错误,要么是文档不足。
关于postgresql - 在表上添加触发器时出现 PSQLException 和锁定问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57681970/
我的应用程序从一个有 5 个选项卡的选项卡栏 Controller 开始。一开始,第一个出现了它的名字,但其他四个没有名字,直到我点击它们。然后根据用户使用的语言显示名称。如何在选项卡栏出现之前设置选
我有嵌套数组 json 对象(第 1 层、第 2 层和第 3 层)。我的问题是数据表没有出现。任何相关的 CDN 均已导入。该表仅显示部分。我引用了很多网站,但都没有解决我的问题。 之前我使用标准表来
我正在尝试设置要显示的 Parse PFLoginViewController。这是我的一个 View Controller 的类。 import UIKit import Parse import
我遇到了这个问题,我绘制的对象没有出现在 GUI 中。我知道它正在被处理,因为数据被推送到日志文件。但是,图形没有出现。 这是我的一些代码: public static void main(Strin
我有一个树状图,其中包含出现这样的词...... TreeMap occurrence = new TreeMap (); 字符串 = 单词 整数 = 出现次数。 我如何获得最大出现次数 - 整数,
因此,我提示用户输入变量。如果变量小于 0 且大于 10。如果用户输入 10,我想要求用户再次输入数字。我问时间的时候输入4,它说你输入错误。但在第二次尝试时效果很好。例如:如果我输入 25,它会打印
我已经用 css overflow 属性做了一个例子。在这个例子中我遇到了一个溢出滚动的问题。滚动条出现了,但没有工作意味着每当将光标移动到滚动条时,在这个滚动条不活动的时间。我对此一无所知,所以请帮
我现在正在做一个元素。当您单击一个元素时,会出现以下信息,我想知道如何在您单击下一个元素而不重新单击同一元素时使其消失....例如,我的元素中有披萨,我想单击肉披萨看到浇头然后点击奶酪披萨看到浇头和肉
我有一个路由器模块,它将主题与正则表达式进行比较,并将出现的事件与一致的键掩码链接起来。 (它是一个简单的 url 路由过滤,如 symfony http://symfony.com/doc/curr
这个问题在这里已经有了答案: 9年前关闭。 Possible Duplicate: mysql_fetch_array() expects parameter 1 to be resource, bo
我在底部有一个带有工具栏的 View ,我正在使用 NavigationLink 导航到该 View 。但是当 View 出现时,工具栏显示得有点太低了。大约半秒钟后,它突然跳到位。它只会在应用程序启
我试图在我的应用程序上为背景音乐添加一个 AVAudioPlayer,我正在主屏幕上启动播放器,尝试在应用程序打开时开始播放但出现意外行为... 它播放并立即不断创建新玩家并播放这些玩家,因此同时播放
这是获取一个数字,获取其阶乘并将其加倍,但是由于基本情况,如果您输入 0,它会给出 2 作为答案,因此为了绕过它,我使用了 if 语句,但收到错误输入“if”时解析错误。如果你们能提供帮助,我真的很感
暂停期间抛出异常 android.os.DeadObjectException 在 android.os.BinderProxy.transactNative( native 方法) 在 androi
我已经为猜词游戏编写了一些代码。它从用户输入中读取字符并在单词中搜索该字符;根据字符是否在单词中,程序返回并控制一些变量。 代码如下: import java.util.Random; import
我是自动化领域的新手。这是我的简单 TestNG 登录代码,当我以 TestNG 身份运行该代码时,它会出现 java.lang.NullPointerException,双击它会突出显示我导航到 U
我是c#程序员,我习惯了c#的封装语法和其他东西。但是现在,由于某些原因,我应该用java写一些东西,我现在正在练习java一天!我要创建一个为我自己创建一个虚拟项目,以便让自己更熟悉 Java 的
我正在使用 Intellij,我的源类是 main.com.coding,我的资源文件是 main.com.testing。我将 spring.xml 文件放入资源文件中。 我的测试类位于 test.
我想要我的tests folder separate到我的应用程序代码。我的项目结构是这样的 myproject/ myproject/ myproject.py moduleon
这个问题已经有答案了: What is a NullPointerException, and how do I fix it? (12 个回答) 已关闭 6 年前。 因此,我尝试比较 2 个值,一个
我是一名优秀的程序员,十分优秀!