我用一个非常有用的答案问了这个问题:
如何对跨多个表的结构进行唯一性约束?
Erwin Brandstetter 的回答表明了这一点:
WITH ins_string_properties AS (
INSERT INTO string_properties (source_id, name, value)
VALUES (gen_random_uuid(), 'slug', 'hello-world')
ON CONFLICT DO NOTHING -- to silence unique violation errors
RETURNING source_id
)
, ins_objects AS (
INSERT INTO objects (id, type)
SELECT o.id, o.type
FROM ins_string_properties isp -- always 0 or 1 rows
CROSS JOIN LATERAL (
VALUES
(isp.source_id , 'baz')
, (gen_random_uuid(), 'foo')
, (gen_random_uuid(), 'bar')
) o(id, type)
RETURNING id, type
)
INSERT INTO object_properties (source_id, name, value_id)
SELECT io1.id, io2.type, io2.id
FROM ins_objects io1
JOIN ins_objects io2 ON io1.type = 'foo' AND io2.type = 'bar'
OR io1.type = 'bar' AND io2.type = 'baz'
;
我只是在学习 CTE,但答案是:
READ COMMITTED
在具有默认事务隔离的并发写入负载下也是安全的。
我将在 CockroachDB 中使用它,他们似乎建议避免READ COMMITTED
使用它SERIALIZABLE
。
我可以将此查询与. 一起使用吗SERIALIZABLE
,或者如果不可以,为什么不 / 必须修改什么以使其与SERIALIZABLE
. 这些事务级别对我来说是新的,过去我主要使用 PostgreSQL 和 Ruby on Rails ORM,所以没有深入研究 SQL。只是尝试使用SERIALIZABLE
CockroachDB 推荐的默认事务隔离级别,并且不确定我是否/何时可以/不能使用它,并且不确定这种情况。
这就是我对READ COMMITTED
vs.的了解SERIALIZABLE
。
实际上,根据手册,这不仅仅是一个建议。CockroachDB 使用
SERIALIZABLE
快照隔离,期:但这对这个解决方案没有任何问题。
SERIALIZABLE
仅比 更严格READ COMMITTED
。如果有的话,您有更多的余地,同时仍然可以安全地应对并发写入负载的竞争条件。这是根据 SQL 标准。但是没有必要,因为解决方案应该尽可能快。问题
SERIALIZABLE
是它更贵。至少在 Postgres 中是这样的。在讨论“Postgres vs CockroachDB”的主题时。手册中的一个建议:
您的表
object_properties
可能应该删除添加的代理id
并PRIMARY KEY (source_id, value_id)
改用 - 也替换我建议CONSTRAINT object_properties_uni UNIQUE (source_id, value_id)
的 .