UNIQUE 约束的事务策略?

Pak*_*Lui 4 postgresql concurrency transaction isolation-level

如何使用基于交易的策略来确保同一地点在同一天不能被多次预订?

有人向我建议,每个隔离级别都会有所不同。你能为他们每个人添加一个例子吗?( read committed,repeatable readserializable)。我想了解他们中的每一个人。

以下是表格和测试数据:

CREATE TABLE place (
  place_id INT                   PRIMARY KEY,
  Name     CHARACTER VARYING(50) NOT NULL,
  Type     CHARACTER VARYING(50) NOT NULL
);

CREATE TABLE visit (
  visit_id SERIAL PRIMARY KEY,
  place_id INT NOT NULL,
  place_dt TIMESTAMP NOT NULL,

  FOREIGN KEY (place_id) REFERENCES place(place_id)
);

INSERT INTO place(place_id, Name, Type
) VALUES
    (1, 'Denali', 'mountain'),
    (2, 'Brindley', 'mountain'),
    (3, 'St. Louis Cathedral', 'church')
;

INSERT INTO visit(place_id, place_dt
) VALUES
    (1, '2019-01-02 10:00'),
    (2, '2019-01-02 11:00'),
    (3, '2019-01-03 14:09')
;
Run Code Online (Sandbox Code Playgroud)

小提琴


我想要的是,对于每个隔离级别,寻找一种基于事务的策略,以确保同一位置在同一天不能被预订多次。

鉴于在这种情况下,策略可能对于各种隔离级别都是最佳的。

Erw*_*ter 6

劳伦斯说的。请注意,Postgres 跨事务隔离边界检查(必须检查)是否存在唯一违规(由重复进入UNIQUE索引引发的异常)。这些检查是“绝对的”。手册中“索引唯一性检查”
一章中的详细信息。

但是使用这个优化的等效解决方案,同时使用它:

CREATE UNIQUE INDEX ON visit (place_id, cast(place_dt AS date));
Run Code Online (Sandbox Code Playgroud)

place_idinteger(4 个字节)。
date_trunc()返回timestamp用于timestamp输入(8个字节)。
date只占用4个字节。
空间通常以 8 字节的倍数分配。

一个索引(integer, timestamp)有效地占用每个索引元组 28 个字节。
一个索引(integer, date)有效地占用每个索引元组 20 个字节。所以另一个是大 40% 没有增益。

更多细节:

旁白:索引还有助于 FK 约束的性能visit (place_id)- 当您place_id放在首位时。


Lau*_*lbe 5

为此,您只需visit在唯一索引的形状上设置约束:

CREATE UNIQUE INDEX ON visit (place_id, date_trunc('day', place_dt));
Run Code Online (Sandbox Code Playgroud)

无论隔离级别如何,这都将保证唯一性。