【问题标题】:php Postgresql pg_query(): duplicate key value violates unique constraintphp Postgresql pg_query():重复键值违反唯一约束
【发布时间】:2016-11-14 05:32:58
【问题描述】:

我们正在重构我们的框架 Postgresql 驱动程序以允许事务。在此过程中,我们引入了一些导致以下错误的问题

pg_query(): duplicate key value violates unique constraint DETAIL: Key (id)=(1) already exists

travis 测试的链接以及更多详细信息 https://travis-ci.org/photodude/database/jobs/175596877

有问题的驱动程序的相关部分在此链接中

https://github.com/joomla-framework/database/blob/master/src/Postgresql/PostgresqlDriver.php#L711-L819

与该问题相关的测试是

https://github.com/joomla-framework/database/blob/master/Tests/DriverPostgresqlTest.php#L1116-L1163

我知道表格序列不知何故搞砸了,但我不知道为什么表格序列搞砸了,甚至不知道如何修复代码以使测试正常运行。

注意:我认为此失败与准备好的和未准备的语句有关

【问题讨论】:

    标签: php postgresql joomla phpunit joomla-framework


    【解决方案1】:

    在第 519 行重新启动序列并截断表,看起来没问题,但如果在回滚事务中运行,截断不会发生,但序列重启 will

        Important: Because sequences are non-transactional, changes made by setval are not undone if the transaction rolls back.
    

    见:

    s1=> create table test1 ( id serial primary key, a text not null);
    CREATE TABLE
    s1=> \d
                 List of relations
     Schema |     Name     |   Type   | Owner  
    --------+--------------+----------+--------
     public | test1        | table    | albert
     public | test1_id_seq | sequence | albert
    (2 rows)
    
    s1=> insert into test1(a) values ('apple');
    INSERT 0 1
    s1=> select * from test1;
     id |   a   
    ----+-------
      1 | apple
    (1 row)
    
    s1=> select * from test1_id_seq;
     sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
    ---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
     test1_id_seq  |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |      32 | f         | t
    (1 row)
    
    s1=> insert into test1(a) values ('bannana');
    INSERT 0 1
    s1=> select * from test1;
     id |    a    
    ----+---------
      1 | apple
      2 | bannana
    (2 rows)
    
    s1=> insert into test1(a) values ('bannana');
    INSERT 0 1
    s1=> select * from test1;
     id |    a    
    ----+---------
      1 | apple
      2 | bannana
      3 | bannana
    (3 rows)
    
    s1=> select * from test1_id_seq;
     sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
    ---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
     test1_id_seq  |          3 |           1 |            1 | 9223372036854775807 |         1 |           1 |      30 | f         | t
    (1 row)
    
    s1=> begin;
    BEGIN
    s1=> alter sequence test1_id_seq RESTART WITH 1;
    ALTER SEQUENCE
    s1=> truncate table test1;
    TRUNCATE TABLE
    s1=> rollback;
    ROLLBACK
    s1=> select * from test1_id_seq;
     sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
    ---------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
     test1_id_seq  |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |       0 | f         | f
    (1 row)
    
    s1=> select * from test1;
     id |    a    
    ----+---------
      1 | apple
      2 | bannana
      3 | bannana
    (3 rows)
    
    s1=>
    

    【讨论】:

    • TRUNCATE ... RESTART IDENTITY也是如此。
    • 这是一个有趣的注释。我不确定它是否适用于这里的具体失败。隔离测试我仍然失败。这似乎与使用准备好的语句有关,因为在仅运行执行测试时我们没有使用事务。
    【解决方案2】:

    我们仍然不确定根本原因,但整个问题与单元测试有关。即使只检查了一个失败的测试,某些东西正在/正在全局重新启动表序列。我们找到了解决问题的方法,但仍在寻找根本原因。

    我们还发现需要改进所有驱动程序测试的 tearDown() 方法。

    【讨论】:

      猜你喜欢
      • 2011-05-25
      • 2016-09-28
      • 2011-10-17
      • 2016-10-24
      • 2014-08-18
      • 2017-12-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多