postgresql临时表的线程安全性
这是我用于创建临时表的语法:
create temp table tmpTable (id bigint not null, primary key (id)) on commit drop;
我知道这意味着在每个事务结束时,此表将被删除。 我的问题是,如果同一会话中的两个或多个线程创建并将值插入临时表,它们每个都会获得自己的实例,还是整个会话中共享的临时实例? 如果它是共享的,有没有办法让它在每个线程本地?
谢谢Netta
临时表对同一会话中的所有操作都是可见的。 因此,在删除存在的临时表之前,不能在同一会话中创建同名的临时表(在您的情况下提交事务)。
您可能想要使用:
CREATE TEMP TABLE tmptbl IF NOT EXISTS ...
有关手册中的CREATE TABLE
更多信息。
独特的临时表
要使临时表在每个“线程”本地(在同一会话中),您需要使用唯一的表名 。 一种方法是使用未绑定的SEQUENCE
和动态SQL – 在程序语言中,如plpgsql或DO语句(在没有存储函数的情况下基本相同)。
运行一个:
CREATE SEQUENCE myseq;
使用:
DO $$ BEGIN EXECUTE 'CREATE TABLE tmp' || nextval('myseq') ||'(id int)'; END; $$
要知道最新的表名:
SELECT 'tmp' || currval('myseq');
或者将它全部放入plpgsql函数并返回表或重用表名。
但是,所有其他SQL命令都必须动态执行,因为纯SQL语句使用硬编码标识符。 因此,将它全部放入plpgsql函数中可能是最好的。
使用相同临时表的唯一ID
另一种可能的解决方案是对同一会话中的所有线程使用相同的临时表 ,并向表中添加列thread_id
。 如果大量使用该function,请务必为该列编制索引。 然后在每个线程中使用唯一的thread_id
(在同一个会话中)。
只有一次:
CREATE SEQUENCE myseq;
每个线程一次:
CREATE TEMP TABLE tmptbl(thread_id int, col1 int) IF NOT EXISTS; my_id := nextval('myseq'); -- in plpgsql -- else find another way to assign unique id per thread
SQL:
INSERT INTO tmptbl(thread_id, col1) VALUES (my_id, 2), (my_id, 3), (my_id, 4); SELECT * FROM tmptbl WHERE thread_id = my_id;