写点什么

pgbench 测试 postgresql 存储过程高并发锁表情况

作者:俞立夫
  • 2024-08-21
    日本
  • 本文字数:1314 字

    阅读完需:约 4 分钟

一个常见的存储过程或者事务处理场景。

先进行 select 查询,然后进行 update。这个时候涉及到 select 行锁。否则,可能会 select 都能过,然后一起进行 update 了。为了避免这种情况,需要在 select 的时候,增加行锁(悲观锁)。具体到业务场景,可能存在查询多个行,只要锁定某个表的某一行数据的情况。所以有了下面的测试示例:

1. 创建表结构

假设你已经有如下的两个表 test_table1test_table2,其中 test_table2test_table1_id 字段与 test_table1 表的 id 字段对应:


CREATE TABLE test_table1 (    id SERIAL PRIMARY KEY,    bz INTEGER NOT NULL DEFAULT 0);
CREATE TABLE test_table2 ( id SERIAL PRIMARY KEY, test_table1_id INTEGER REFERENCES test_table1(id), other_data TEXT);
-- 插入示例数据INSERT INTO test_table1 (bz) VALUES (0), (0), (1); -- id 为 1, 2, 3INSERT INTO test_table2 (test_table1_id, other_data) VALUES (1, 'data1'), (2, 'data2'), (3, 'data3');
复制代码

2. 存储过程

将存储过程更新为使用 test_table1test_table2


CREATE OR REPLACE FUNCTION update_if_not_updated() RETURNS TEXT AS $$DECLARE    test_table1_record RECORD;    found_record BOOLEAN := FALSE;  -- 标志变量,记录是否找到匹配的记录BEGIN    -- 联表查询并只锁定 test_table1 表中的行    FOR test_table1_record IN        SELECT a.*        FROM test_table1 a, test_table2 b        WHERE a.id = b.test_table1_id AND a.bz = 0        FOR UPDATE OF a    LOOP        found_record := TRUE;  -- 找到匹配记录,设置标志为 TRUE                -- 检查是否需要更新        IF test_table1_record.bz = 0 THEN            -- 更新 test_table1 表的 bz 字段            UPDATE test_table1 SET bz = 1 WHERE id = test_table1_record.id;            RAISE NOTICE 'Thread %: 更新成功, id = %, bz = 1', pg_backend_pid(), test_table1_record.id;            RETURN '更新成功';        ELSE            RAISE NOTICE 'Thread %: 已被更新, id = %', pg_backend_pid(), test_table1_record.id;            RETURN '已被更新';        END IF;    END LOOP;
-- 如果没有找到任何记录 IF NOT found_record THEN RAISE NOTICE 'Thread %: 没有找到符合条件的记录', pg_backend_pid(); RETURN '没有找到符合条件的记录'; END IF;
RETURN '没有可更新的记录';END;$$ LANGUAGE plpgsql;
复制代码

3. 使用 pgbench 进行并发测试

创建一个 SQL 脚本文件(例如 test_script.sql)来执行存储过程:


SELECT update_if_not_updated();
复制代码


然后使用 pgbench 命令进行并发测试:


pgbench -c 5 -j 2 -t 10 -f test_script.sql your_database_name
复制代码


  • -c 5: 5 个并发客户端。

  • -j 2: 2 个线程。

  • -t 10: 每个客户端执行 10 次。

  • -f test_script.sql: 使用你创建的 SQL 脚本文件。

4. 检查结果

测试完成后,查看 test_table1 的状态,验证并发更新操作是否如预期:


SELECT * FROM test_table1;
复制代码


pgbench 环境中测试并发操作对 test_table1test_table2 的影响。


发布于: 刚刚阅读数: 4
用户头像

俞立夫

关注

还未添加个人签名 2018-08-07 加入

还未添加个人简介

评论

发布
暂无评论
pgbench测试postgresql存储过程高并发锁表情况_postgresql_俞立夫_InfoQ写作社区