首页 > 解决方案 > 关于在 jmeter 中运行的 postgres 函数测试的问题

问题描述

我正在 jmeter 中测试一个 plpgsql 函数。以下示例是复制该问题。我有一个名为 sing 的表,其定义如下

db=# \d 唱

表“schema1.sing”

柱子 类型
ID 大整数
瓦尔 数字

我的plpgsql函数如下

create or replace function schema1.insissue(val text) returns text as $$
declare
  _p text;_h text;
  ids text[];
  valid numeric := functiontochangetoid(val); // a sample function to change value into id.
  slid bigint:= nextval('rep_s'); // sequence value
  dup text := null;
begin
 select array_agg(id) from sing where valr = valid into ids;
 raise notice 'ids %',ids;
 if coalesce(array_upper(ids,1),0) > 0 then
   dup = 'FAIL';
 end if;
 raise notice 'dup %',dup;
 if dup is null then
  insert into sing values (slid,valid);
  return 'SUCCESS'|| slid;
 end if;
  return 'FAIL';
exception
  when others then
  get stacked diagnostics
  _p := pg_exception_context,_h := pg_exception_hint;
  raise notice 'sqlerrm >> :%',sqlerrm;
  raise notice 'position >> :%',_p;
  raise notice 'hint >> :%',_h;
  return 'FAIL';
end;
$$ language plpgsql;

只需在我的函数中,它会检查该值是否存在于 sing 表的 valr 列中,如果不存在则将该值插入表中。

现在我的 jmeter 配置 连接配置

用户线程

采样器

连接我使用 postgresql-42.2.14.jar。当加速周期为 1 秒 IE 200 请求在一秒内时,该函数会创建这样的重复值,当加速周期为 100 秒时没有问题。

db=# select * from sing;

ID 瓦尔
897 1095
898 1095
89+ 1095
900 1095
901 1095
902 1095
903 1095

但实际上应该是这样的

db=# select * from sing;

ID 瓦尔
897 1095

我怎样才能避免这些类型的重复值?因为我的应用程序将有高流量可能是 100 次调用,我也不能将“valr”列作为主键。因为它包含其他类型的值。

我的 postgres 版本

    db=# select version();
                                                     version                                                      
------------------------------------------------------------------------------------------------------------------
 PostgreSQL 12.3 (Debian 12.3-1.pgdg100+1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit

标签: javapostgresqltestingjdbcjmeter

解决方案


终于找到了解决方案,序列化的事务隔离适用于我的实际问题。查看此链接https://www.postgresql.org/docs/12/sql-set-transaction.html。默认情况下,事务是读取提交的。当我们在会话上将事务更改为序列化时,它会起作用。要使事务序列化,您可以在任何选择查询之前在会话上使用 set 命令

 SET transaction isolation level serializable;

它不能在 PostgreSQL 的函数或过程中仅用于会话。我们可以在程序中使用 set 但会出现这样的错误

NOTICE:  sqlerrm >> :SET TRANSACTION ISOLATION LEVEL must be called before any query
NOTICE:  position >> :SQL statement "SET transaction isolation level serializable"


推荐阅读