Dear Hou,

Thanks for updating the patch! Here are my comments.

01. CreateSubscription
```
+    if (opts.detectupdatedeleted && !track_commit_timestamp)
+        ereport(ERROR,
+                errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+                errmsg("detecting update_deleted conflicts requires \"%s\" to 
be enabled",
+                       "track_commit_timestamp"));
```

I don't think this guard is sufficient. I found two cases:

* Creates a subscription with detect_update_deleted = false and 
track_commit_timestamp = true,
  then alters detect_update_deleted to true.
* Creates a subscription with detect_update_deleted = true and 
track_commit_timestamp = true,
  then update track_commit_timestamp to true and restart the instance.

Based on that, how about detecting the inconsistency on the apply worker? It 
check
the parameters and do error out when it starts or re-reads a catalog. If we want
to detect in SQL commands, this can do in parse_subscription_options().

02. AlterSubscription()
```
+                    ApplyLauncherWakeupAtCommit();
```

The reason why launcher should wake up is different from other parts. Can we 
add comments
that it is needed to track/untrack the xmin?

03. build_index_column_bitmap()
```
+    for (int i = 0; i < indexinfo->ii_NumIndexAttrs; i++)
+    {
+        int         keycol = indexinfo->ii_IndexAttrNumbers[i];
+
+        index_bitmap = bms_add_member(index_bitmap, keycol);
+    }
```

I feel we can assert the ii_IndexAttrNumbers is valid, because the passed index 
is a replica identity key.

04. LogicalRepApplyLoop()

Can we move the definition of "phase" to the maybe_advance_nonremovable_xid() 
and
make it static? The variable is used only by the function.

05. LogicalRepApplyLoop()
```
+                        UpdateWorkerStats(last_received, timestamp, false);
```

The statistics seems not correct. last_received is not sent at "timestamp", it 
had
already been sent earlier. Do we really have to update here?

06. ErrorOnReservedSlotName()

I feel we should document that the slot name 'pg_conflict_detection' cannot be 
specified
unconditionally.

07. General

update_deleted can happen without DELETE commands. Should we rename the conflict
reason, like 'update_target_modified'?

E.g., there is a 2-way replication system and below transactions happen:

Node A:
  T1: INSERT INTO t (id, value) VALUES (1,1); ts = 10.00
  T2: UPDATE t SET id = 2 WHERE id = 1; ts = 10.02
Node B:
  T3: UPDATE t SET value = 2 WHERE id = 1; ts = 10.01

Then, T3 comes to Node A after executing T2. T3 tries to find id = 1 but find a
dead tuple instead. In this case, 'update_delete' happens without the delete.

08. Others

Also, here is an analysis related with the truncation of commit timestamp. I 
worried the
case that commit timestamp might be removed so that the detection would not go 
well.
But it seemed that entries can be removed when it behinds 
GetOldestNonRemovableTransactionId(NULL),
i.e., horizons.shared_oldest_nonremovable. The value is affected by the 
replication
slots so that interesting commit_ts entries for us are not removed.

Best regards,
Hayato Kuroda
FUJITSU LIMITED

Reply via email to