简体   繁体   English

Postgres 序列不同步

[英]Postgres Sequence out of sync

I'm running a multi-master setup with bucardo and postgres.我正在使用 bucardo 和 postgres 运行多主设置。

I'm finding that some of my table sequences are getting out of sync with each other.我发现我的一些表格序列彼此不同步。 Particularly the auto-incremented id.特别是自动递增的 id。

example:例子:

db1 - table1 db1 - 表 1

INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')

The id of the new row is 1新行的id为1

db2 - table1 db2 - 表 1

INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')

The id of the new row is 1新行的id为1

The id of the new row on db2 should be 2, because bucardo has replicated the data from db1, but db2's auto increment is based on: db2 上新行的 id 应该是 2,因为 bucardo 已经从 db1 复制了数据,但是 db2 的自动增量是基于:

nextval('oauth_sessions_id_seq'::regclass)

And if we check the "oauth_sessions_id_seq" we see the last value as 0.如果我们检查“oauth_sessions_id_seq”,我们会看到最后一个值为 0。

phew... Make sense?呼...有道理吗?

Anyway, can I do any of the following?无论如何,我可以执行以下任何操作吗?

  1. Replicate the session tables with bucardo, so each DB's session is shared?使用 bucardo 复制会话表,以便共享每个数据库的会话?

  2. Manipulate the default auto-increment function above to take into account the max existing items in the table?操作上面的默认自动增量函数以考虑表中的最大现有项目?

If you have any better ideas, please feel free to throw them in. Questions just ask, thanks for any help.如果您有任何更好的想法,请随时提出。问题只是提出,感谢您的帮助。

You are going to have to change your id generation method, because there is no Bucardo solution according to this comment in the FAQ.您将不得不更改您的 id 生成方法,因为根据常见问题解答中的此评论,没有 Bucardo 解决方案。

Can Bucardo replicate DDL? Bucardo 可以复制 DDL 吗?

No, Bucardo relies on triggers, and Postgres does not yet provide DDL triggers or triggers on its system tables.不,Bucardo 依赖于触发器,而 Postgres 尚未提供 DDL 触发器或在其系统表上提供触发器。

Since Bucardo uses triggers, it cannot "see" the sequence changes, only the data in tables, which it replicates.由于 Bucardo 使用触发器,它无法“看到”序列变化,只能看到它复制的表中的数据。 Sequences are interesting objects that do not support triggers, but you can manually update them.序列是不支持触发器的有趣对象,但您可以手动更新它们。 I suppose you could add something like the code below before the INSERT , but there still might be issues.我想您可以在INSERT之前添加类似以下代码的内容,但仍然可能存在问题。

SELECT setval('oauth_sessions_id_seq', (SELECT MAX(did) FROM distributors));

See this question for more information.有关更多信息,请参阅此问题

I am not fully up on all the issues involved, but you could perform the maximum calculation manually and do the insert operation in a re-try loop.我还没有完全了解所涉及的所有问题,但您可以手动执行最大计算并在重试循环中执行插入操作。 I doubt it will work if you are actually doing inserts on both DBs and allowing Bucardo to replicate, but if you can guarantee that only one DB updates at a time, then you could try something like an UPSERT retry loop.如果您实际上在两个数据库上进行插入并允许 Bucardo 复制,我怀疑它会起作用,但是如果您可以保证一次只更新一个数据库,那么您可以尝试类似UPSERT重试循环的方法。 See this post for more info.有关更多信息,请参阅此帖子 The "guts" of the loop might look like this:循环的“胆量”可能如下所示:

INSERT INTO  distributors (did, dname) 
    VALUES ((SELECT max(did)+1 FROM distributors), 'XYZ Widgets');

Irrespective of the DB (PostgreSQL, Oracle, etc.), dynamic sequence was created for each of the table which has the primary key associated with it.无论数据库(PostgreSQL、Oracle 等)如何,都会为每个具有与其关联的主键的表创建动态序列。 Most of the sequences go out of sync whenever a huge import of data is happened or some person has manually modified the sequence of the table.每当发生大量数据导入或有人手动修改表的序列时,大多数序列都会不同步。

Solution: The only way we can set back the sequence is by taking the max value of the PK table and set the sequence next val to it.解决方案:我们可以回退序列的唯一方法是取PK表的最大值并将序列next val设置为它。

The below query will list you out all the sequences created in your DB schema:以下查询将列出在您的数据库架构中创建的所有序列:

SELECT c.relname FROM pg_class c WHERE c.relkind = 'S';

SELECT MAX('primary_key') from table;

SELECT setval('the_primary_key_sequence', (SELECT MAX(the_primary_key) FROM the_table)+1);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM