-
Notifications
You must be signed in to change notification settings - Fork 61
debezium: output start_ts in the source block of DML messages #5903
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
90947b6
bc7c56b
492dbbc
56d0dc5
7bda3ca
947ad62
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -886,7 +886,10 @@ func (c *dbzCodec) writeBinaryField(writer *util.JSONWriter, fieldName string, v | |||||||||||||||||||||
| writer.WriteBase64StringField(fieldName, value) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
| func (c *dbzCodec) writeSourceSchema(writer *util.JSONWriter, schemaName string) { | ||||||||||||||||||||||
| // includeStartTs indicates whether start_ts should be declared in the source | ||||||||||||||||||||||
| // schema. DML callers pass the configured value, while DDL, checkpoint, and | ||||||||||||||||||||||
| // Avro callers pass false because their payloads do not carry the field. | ||||||||||||||||||||||
| func (c *dbzCodec) writeSourceSchema(writer *util.JSONWriter, schemaName string, includeStartTs bool) { | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like only dml will carry the start ts field?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, only DML events |
||||||||||||||||||||||
| writer.WriteObjectElement(func() { | ||||||||||||||||||||||
| writer.WriteStringField("type", "struct") | ||||||||||||||||||||||
| writer.WriteArrayField("fields", func() { | ||||||||||||||||||||||
|
|
@@ -987,6 +990,13 @@ func (c *dbzCodec) writeSourceSchema(writer *util.JSONWriter, schemaName string) | |||||||||||||||||||||
| writer.WriteStringField("field", "cluster_id") | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| if includeStartTs { | ||||||||||||||||||||||
| writer.WriteObjectElement(func() { | ||||||||||||||||||||||
| writer.WriteStringField("type", "int64") | ||||||||||||||||||||||
| writer.WriteBoolField("optional", false) | ||||||||||||||||||||||
| writer.WriteStringField("field", "start_ts") | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| writer.WriteBoolField("optional", false) | ||||||||||||||||||||||
| writer.WriteStringField("name", c.sourceSchemaName(schemaName)) | ||||||||||||||||||||||
|
|
@@ -1084,6 +1094,11 @@ func (c *dbzCodec) EncodeValue( | |||||||||||||||||||||
|
|
||||||||||||||||||||||
| // The followings are TiDB extended fields | ||||||||||||||||||||||
| jWriter.WriteUint64Field("commit_ts", e.CommitTs) | ||||||||||||||||||||||
| // start_ts: the start TSO of the transaction that made this change, | ||||||||||||||||||||||
| // exposed for downstream consumers that need transaction correlation. | ||||||||||||||||||||||
| if c.config.DebeziumIncludeStartTs { | ||||||||||||||||||||||
| jWriter.WriteUint64Field("start_ts", e.StartTs) | ||||||||||||||||||||||
| } | ||||||||||||||||||||||
|
Comment on lines
+1097
to
+1101
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win Exclude Line 1099 does not check This breaks the Avro payload/schema contract and fails the Avro exclusion test. Gate the payload write with the same Avro condition as the schema. Proposed fix- if c.config.DebeziumOutputStartTs {
+ if c.config.DebeziumOutputStartTs && !c.isDebeziumAvro() {
jWriter.WriteUint64Field("start_ts", e.StartTs)
}📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||
| jWriter.WriteStringField("cluster_id", c.clusterID) | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
|
|
@@ -1176,7 +1191,7 @@ func (c *dbzCodec) EncodeValue( | |||||||||||||||||||||
| jWriter.WriteRaw(fieldsJSON) | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| }) | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, schemaName) | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, schemaName, c.config.DebeziumIncludeStartTs) | ||||||||||||||||||||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this affect the Debezium-Avro protocol?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. Debezium Avro explicitly calls |
||||||||||||||||||||||
| jWriter.WriteObjectElement(func() { | ||||||||||||||||||||||
| jWriter.WriteStringField("type", "string") | ||||||||||||||||||||||
| jWriter.WriteBoolField("optional", false) | ||||||||||||||||||||||
|
|
@@ -1464,7 +1479,7 @@ func (c *dbzCodec) EncodeDDLEvent( | |||||||||||||||||||||
| jWriter.WriteIntField("version", 1) | ||||||||||||||||||||||
| jWriter.WriteStringField("name", "io.debezium.connector.mysql.SchemaChangeValue") | ||||||||||||||||||||||
| jWriter.WriteArrayField("fields", func() { | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, dbName) | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, dbName, false) | ||||||||||||||||||||||
| jWriter.WriteObjectElement(func() { | ||||||||||||||||||||||
| jWriter.WriteStringField("field", "ts_ms") | ||||||||||||||||||||||
| jWriter.WriteBoolField("optional", false) | ||||||||||||||||||||||
|
|
@@ -1703,7 +1718,7 @@ func (c *dbzCodec) EncodeCheckpointEvent( | |||||||||||||||||||||
| fmt.Sprintf("%s.%s.Envelope", common.SanitizeName(c.clusterID), "watermark")) | ||||||||||||||||||||||
| jWriter.WriteIntField("version", 1) | ||||||||||||||||||||||
| jWriter.WriteArrayField("fields", func() { | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, "watermark") | ||||||||||||||||||||||
| c.writeSourceSchema(jWriter, "watermark", false) | ||||||||||||||||||||||
| jWriter.WriteObjectElement(func() { | ||||||||||||||||||||||
| jWriter.WriteStringField("type", "string") | ||||||||||||||||||||||
| jWriter.WriteBoolField("optional", false) | ||||||||||||||||||||||
|
|
||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Preserve
output_old_valuewhen onlyinclude_start_tsis providedA partial v2 update such as:
silently changes
output_old_valuefrom its defaulttruetofalse.UpdateChangefeed decodes into an empty config, andDebeziumConfig.OutputOldValueis a non-pointer bool, so an omitted field becomes false. The conversion here then copies that zero value into a newly constructed internalDebeziumConfig, overriding the default. Consequently, Debezium update events stop carrying the before value even though the user only enabled start_ts.Please make the API field optional (for example,
OutputOldValue *bool) and only override the existing/default internal value when it is non-nil. Please also add a unit test to cover this case.