400 Star 1.3K Fork 1.5K

GVPopenGauss / openGauss-server

 / 详情

在表中同时有自增主键和时间戳字段情况下,会出现ID大但是时间戳小的记录

已取消
缺陷
创建于  
2023-12-21 17:05

【标题描述】:在表中同时有自增主键和时间戳字段情况下,会出现ID大但是时间戳小的记录
【测试类型:SQL功能】
【测试版本:openGauss 5.0.0 build a07d57c3】
问题描述

【操作系统和硬件信息】(查询命令: cat /etc/system-release, uname -a):
cat /etc/system-release
openEuler release 22.03 (LTS-SP1)
uname -a
Linux xxxxxx 5.10.0-136.12.0.86.oe2203sp1.aarch64 #1 SMP Tue Dec 27 17:51:19 CST 2022 aarch64 aarch64 aarch64 GNU/Linux

【测试环境】(单机/1主x备x级联备):
1主1备
【被测功能】:
表自增主键和时间戳字段
【测试类型】:

【数据库版本】(查询命令: gaussdb -V):
gaussdb -V
gaussdb (openGauss 5.0.0 build a07d57c3) compiled at 2023-03-29 03:36:31 commit 0 last mr
【预置条件】:

【操作步骤】(请填写详细的操作步骤):
在表中同时有自增主键和时间戳字段情况下,会出现ID大但是时间戳小的记录

  1. 创建测试表
CREATE TABLE t3 (
    id BIGSERIAL primary key,
    created_time timestamp DEFAULT pg_systimestamp(),
    email character varying(40) NOT NULL
);
  1. 查看自增长ID使用的序列的DDL, 确认其中cache是1
CREATE  SEQUENCE t3_id_seq
 START  WITH  1
 INCREMENT  BY  1
 NO MINVALUE  
 MAXVALUE 9223372036854775807
 CACHE 1;
  1. 开2个终端同时插入100万数据
INSERT INTO t3(email)
SELECT
  'user_' || seq || '@' || (
    CASE (RANDOM() * 2)::INT
      WHEN 0 THEN 'gmail'
      WHEN 1 THEN 'hotmail'
      WHEN 2 THEN 'yahoo'
    END
  ) || '.com' AS email
FROM GENERATE_SERIES(1, 1000000) seq;
  1. 发现出现ID大,但是时间戳小 (或者说ID 小,但是时间戳大的记录)
select * 
from t3 a, t3 b
where 
a.id>=400000
and b.id>=400000
and a.id<500000
and b.id<500000
and a.created_time<b.created_time
and a.id>b.id;

【预期输出】:
无记录返回

【实际输出】:
448362 2023-12-19 21:48:22 user_438351@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448363 2023-12-19 21:48:22 user_438352@yahoo.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448364 2023-12-19 21:48:22 user_438353@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448365 2023-12-19 21:48:22 user_438354@gmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448366 2023-12-19 21:48:22 user_438355@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448367 2023-12-19 21:48:22 user_438356@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448368 2023-12-19 21:48:22 user_438357@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448369 2023-12-19 21:48:22 user_438358@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com
448370 2023-12-19 21:48:22 user_438359@hotmail.com 448361 2023-12-19 21:48:29 user_1@hotmail.com

【原因分析】:

  1. 这个问题的根因
  2. 问题推断过程
  3. 还有哪些原因可能造成类似现象
  4. 该问题是否有临时规避措施
  5. 问题解决方案
  6. 预计修复问题时间

【日志信息】(请附上日志文件、截图、coredump信息):

【测试代码】:

评论 (5)

ogdba 创建了缺陷

Hey @ogdba, Welcome to openGauss Community.
All of the projects in openGauss Community are maintained by @opengauss_bot.
That means the developers can comment below every pull request or issue to trigger Bot Commands.
Please follow instructions at Here to find the details.

Hi @ogdba, please use the command /sig xxx to add a SIG label to this issue.
For example: /sig sqlengine or /sig storageengine or /sig om or /sig ai and so on.
You can find more SIG labels from Here.
If you have no idea about that, please contact with @xiangxinyong , @zhangxubo .

ogdba 修改了描述
jiexiao1413 负责人设置为pengjiong
pengjiong 添加协作者pengjiong
pengjiong 负责人pengjiong 修改为Cross-罗
Cross-罗 修改了描述
Cross-罗 修改了描述

目前认为这个问题是非问题 ,获取时间戳的函数和获取自增键值的函数是两个函数,这两个函数执行的流程并不满足并发的原子性,这就在多线程的情况下,并没有办法保证获取自增键和获取时间戳的先后顺序是一致的。

另外,插入的方法也不对,因为整个语句都在同一个事务当中,而pg_systimestamp()的返回值是根据事务中的一些信息计算决定的,其计算的时间戳依赖于为stmtSysGTMdeltaTimestamp和t_thrd.time_cxt.stmt_system_timestamp的变量,stmtSysGTMdeltaTimestamp变量仅在SetStmtSysGTMDeltaTimestamp函数中初始化,且仅在开启事务的时候被调用
输入图片说明
而t_thrd.time_cxt.stmt_system_timestamp变量则在SetCurrentStmtTimestamp函数中被调用,通过GDB断点调试发现在一个事务开启的过程中,SetCurrentStmtTimestamp函数仅仅呗StartTransaction函数调用了一次,
输入图片说明
所以可知在同一个事务中,pg_systimestamp()返回的时间戳不变,所以上述的使用必然会出现ID大时间戳小的情况,毕竟两边的时间戳本身有先后且大小一直没有变化,但是自增键是有两个线程进行竞争的。可以尝试使用下面的方法进行数据插入

drop table if exists t3;
CREATE TABLE t3 (
    id BIGSERIAL primary key,
    created_time timestamp DEFAULT pg_systimestamp(),
    email character varying(40) NOT NULL
);
DO $$DECLARE i record; 
BEGIN 
    FOR i IN 1..10000   
    LOOP 
    execute 'insert into t3(email) select ''test2@qq.com'';';
    END LOOP;
END$$;

这样,插入数据的语句就会产生10000个事务,产生的时间戳自然就会有变化。

2024年1月3日发起未复现或者未响应公示, 2024年1月16日公示满关闭,后续有问题可再次提单。

周斌 任务状态待办的 修改为已取消

登录 后才可以发表评论

状态
负责人
项目
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
预计工期 (小时)
参与者(4)
13084139 opengauss bot 1686829535
C++
1
https://gitee.com/opengauss/openGauss-server.git
git@gitee.com:opengauss/openGauss-server.git
opengauss
openGauss-server
openGauss-server

搜索帮助