我有两张 PostgreSQL 表:objects
和metadata
。每个对象都有一个size
属性,表示其大小(以字节为单位),并且可以存储在一个唯一的位置storage_id
。元数据中维护了total_size
每个存储中所有对象的 ,每个存储的 都具有给定的storage_id
。简化表格:
CREATE TABLE IF NOT EXISTS objects (
object_id UUID PRIMARY KEY,
storage_id UUID NOT NULL,
size BIGINT NOT NULL,
FOREIGN KEY (storage_id) REFERENCES metadata(storage_id)
);
CREATE TABLE IF NOT EXISTS metadata (
storage_id UUID PRIMARY KEY,
total_size BIGINT DEFAULT 0
);
为了维护表total_size
中的内容metadata
,我有一个触发器,每当插入或删除对象时,total_size
就会更新,即这里是插入的触发器:
CREATE OR REPLACE FUNCTION update_size_on_insert() RETURNS TRIGGER AS $$
BEGIN
UPDATE metadata
SET total_size = total_size + NEW.size
WHERE storage_id = NEW.storage_id;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE TRIGGER trg_update_size_on_insert
AFTER INSERT ON objects
FOR EACH ROW
EXECUTE FUNCTION update_size_on_insert();
问题是并发插入/删除操作可能会覆盖 ,total_size
从而导致数据无效。如何更改触发器,使其在 执行时包含行级SET total_size = total_size + NEW.size
锁?我考虑过FOR UPDATE
语句,但这需要一个SELECT
。我可以使用PERFORM ... FOR UPDATE;
来锁定行吗?