postgresql临时表的线程安全性

时间:2012-05-15 08:30:19

标签: java postgresql

这是我用来创建临时表的语法:

create temp table tmpTable (id bigint not null, primary key (id)) on commit drop;

我知道这意味着在每个事务结束时,此表将被删除。 我的问题是,如果同一会话中的两个或多个线程创建并将值插入临时表,它们每个都会获得自己的实例,还是整个会话中共享的临时实例?如果它是共享的,有没有办法让它在每个线程中都是本地的?

由于 Netta

1 个答案:

答案 0 :(得分:8)

临时表对同一会话中的所有操作都是可见的。因此,您无法在删除存在的临时表>之前>创建一个同名的临时表(在您的情况下提交事务)。

您可能想要使用:

CREATE TEMP TABLE tmptbl IF NOT EXISTS ...

More about CREATE TABLE in the manual.


独特临时表

要在每个“线程”(在同一会话中)使临时表本地化,您需要使用唯一表名。一种方法是使用未绑定的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 列。如果您大量使用该功能,请务必为该列编制索引。然后在每个线程中使用一个唯一的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;