Hello everyone.

I am working on a database migration from old post PostgreSQL 10 hosted in a 
Stolon in Kubernetes (yes I know, it's looking for troubles) to a managed AWS 
RDS Postgresql 15 database.

The only potential solution I found to do this migration is to use the logical 
replication, as we can't have much downtime and the database is quite big 
(around 2TB).

I made many tests on multiple non production environments and had quite strange 
results, on our staging platform for example I could not, so far, achieve a 
complete migration, I had many issues of EOF during wal streaming, I then 
tweaked the wal_sender_timeout and wal_received timeout when I tested the 
migration on the production database and it looks like this part of the issue 
is solved. (I will have to retest it on staging, I tested on production as 
maybe only staging had this issue)
2 others environment were able to do the migration correctly (same schema, 
without the WAL timeout tweaks), one being around 800GB, like staging and the 
other much smaller, around 80GB).

Apart from the timeout issue that looks solved so far, I have a problem with 
our biggest table (which is a link table for a many 2 many relation), it's the 
one that were usually failing on staging and now also failing on the production 
test migration.

There you have the information about the table in question :

back=> \d+ diagnostics_episodes
                               Table "public.diagnostics_episodes"
    Column     |  Type   | Collation | Nullable | Default | Storage | Stats 
target | Description
---------------+---------+-----------+----------+---------+---------+--------------+-------------
 diagnostic_id | bigint  |           |          |         | plain   |           
   |
 episode_id    | bigint  |           |          |         | plain   |           
   |
 is_deleted    | boolean |           | not null | false   | plain   |           
   |
Indexes:
    "diagnostics_episodes_unique" UNIQUE, btree (diagnostic_id, episode_id)
    "index_diagnostics_episodes_on_episode_id" btree (episode_id)
Check constraints:
    "diagnostics_episodes_diagnostic_id_null" CHECK (diagnostic_id IS NOT NULL)
    "diagnostics_episodes_episode_id_null" CHECK (episode_id IS NOT NULL)
Foreign-key constraints:
    "fk_rails_11c88d28cf" FOREIGN KEY (episode_id) REFERENCES episodes(id) ON 
UPDATE CASCADE ON DELETE CASCADE
    "fk_rails_5857fe47a7" FOREIGN KEY (diagnostic_id) REFERENCES 
diagnostics(id) ON UPDATE CASCADE ON DELETE CASCADE
Replica Identity: FULL
Access method: heap

The table size is around 279 GB (from \d)

We had to use replica identity full on this table as setting the replica 
identity to the unique index would require downtime to add the NOT NULL 
constraints on the 2 FK columns.

And this is the current state of the replication, all the tables are in R 
state, except this single table still stuck in F state, it looks like it is 
also blocking the main replication slot of the logical replication ?
(I restarted the postgresql not long ago to check if it would unblock it, no 
luck)

SUBSCRIBER: 

back=> SELECT
  pss.relid, pss.relid::regclass AS obj,
  pss.pid, pss.latest_end_time, pg_size_pretty(pspc.bytes_processed) as 
data_copied,
  pspc.tuples_processed,
  NOW() - pss.last_msg_receipt_time as age
FROM
  pg_stat_subscription AS pss
LEFT JOIN
  pg_stat_progress_copy AS pspc ON pss.pid = pspc.pid;
 relid |         obj          | pid  |        latest_end_time        | 
data_copied | tuples_processed |       age
-------+----------------------+------+-------------------------------+-------------+------------------+-----------------
       |                      | 6346 | 2023-06-09 08:39:23.523942+00 |          
   |                  | 00:09:57.941278
 16923 | diagnostics_episodes | 6347 | 2023-06-09 08:39:23.87963+00  |          
   |                  | 00:08:31.553164
(2 rows)


PUBLISHER:

production=# SELECT
  prs.slot_name, prs.slot_type, prs.database, psa.wait_event,
  psr.state, prs.temporary, prs.active, prs.active_pid, prs.restart_lsn,
  prs.confirmed_flush_lsn
FROM
  pg_replication_slots AS prs
LEFT JOIN
  pg_stat_activity AS psa ON prs.active_pid = psa.pid
LEFT JOIN
  pg_stat_replication AS psr ON psa.pid = psr.pid
WHERE
  prs.slot_type = 'logical';
                slot_name                | slot_type |  database  |     
wait_event     |  state  | temporary | active | active_pid | restart_lsn  | 
confirmed_flush_lsn
-----------------------------------------+-----------+------------+--------------------+---------+-----------+--------+------------+--------------+---------------------
 azure_to_aws                            | logical   | production | 
WalSenderWriteData | catchup | f         | t      |      21534 | A6F/1EF5C210 | 
A6F/1F48F728
 pg_17845_sync_16923_7225826535892257639 | logical   | production | 
WalSenderWriteData | catchup | f         | t      |      21537 | A6D/22E49068 | 
A6D/22EDF188
(2 rows)

(the restart_lsn and confirmed_flush_lsn are not changing over time)

production=# SELECT
  prs.slot_name, prs.active, psr.state, prs.active_pid,
  pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),
  prs.confirmed_flush_lsn)) AS diff_size
FROM
  pg_replication_slots AS prs
LEFT JOIN pg_stat_replication AS psr ON prs.slot_name = psr.application_name
WHERE
  prs.slot_type = 'logical';
                slot_name                | active |  state  | active_pid | 
diff_size
-----------------------------------------+--------+---------+------------+-----------
 azure_to_aws                            | t      | catchup |      21534 | 2855 
MB
 pg_17845_sync_16923_7225826535892257639 | t      | catchup |      21537 | 11 GB
(2 rows)


Something I can see on the monitoring of the subscriber is that it's doing a 
lot of read activity (I can't get more info as it's on RDS so no strace, 
etc..), I can see it's reading at around 400MBps non stop (and it stops if I 
disable the subscription and terminate the process related to the replication), 
but I don't see any write going thru.
On either side I don't see any error on the logs, on the subscriber I have the 
debug5 level log and I don't see any transaction being applied either by the 
replication worker.
On pg_stat_activity I see the logical replication worker of this table always 
active, sometime doing IO:DateFileRead, the main replication worker however is 
always "idle" waiting for IPC:LogicalFileSyncChange

I am not sure what do to next ? I have been trying to troubleshoot this for a 
week but no luck, I also got some help on the PostgreSQL slack server but we 
are not 100% sure of what could be the issue either ( 
https://postgresteam.slack.com/archives/C0FS3UTAP/p1686041198195869 )
On the loadtest environment I first migrated, I saw it had the NOT NULL 
constraint set on the columns of the table (but still with the REPLICA IDENTITY 
FULL) and it worked, I tried to remove the NOT NULL constraint and do again the 
migration and it still worked, so I am not sure it is related to that on the 
other environments?
What could be the other causes of this ?

Thank you.



Reply via email to