Compartilhar via


Formato de mensagem JSON – alterar o streaming de eventos

Aplica-se a: SQL Server 2025 (17.x) Banco de Dados SQL do Azure

Este artigo descreve o formato JSON de uma mensagem CloudEvents que é transmitida do SQL Server para o Azure Event Hubs ao utilizar o recurso de mudança de fluxo de eventos (CES) introduzido no SQL Server 2025 (17.x) e no Azure SQL Database.

Observação

O streaming de eventos de alteração está atualmente em versão prévia para:

Durante a visualização, esse recurso está sujeito a alterações. Para obter suporte atual, consulte Limitações.

Visão geral

Os eventos emitidos pelo streaming de eventos de alteração seguem a especificação CloudEvents , facilitando a integração com sistemas controlados por eventos. Todos os CES CloudEvents contêm 11 atributos (campos). O CES pode ser configurado para serializar CloudEvents como JSON (nativo) ou como binário do Avro. As seções a seguir deste artigo descrevem o formato da mensagem em detalhes, incluindo atributos CES CloudEvent e serialização.

Quando aplicável, as descrições nesta seção são retiradas da especificação CloudEvent, que inclui detalhes adicionais.

Atributos

  • specversion:

    • Tipo de dados: Cadeia
    • Atributo CloudEvent necessário
    • A versão da especificação CloudEvents que o evento usa. Isso permite a interpretação do contexto.
  • type

    • Tipo de dados: Cadeia
    • Atributo CloudEvent necessário
    • Contém um valor que descreve o tipo de evento relacionado à ocorrência de origem. O formato disso é definido pelo produtor e pode incluir informações como a versão do tipo. Para obter mais informações, examine o controle de versão do CloudEvents.
    • Para eventos de Streaming de Eventos de Alteração, o tipo atualmente é: com.microsoft.SQL.CES.DML.V{n}, onde {n} indica a versão do esquema de eventos DML do Microsoft Change Event Streaming.
      • A versão mais recente do esquema é 1.
  • source

    • Tipo de dados: Cadeia
    • Atributo CloudEvent necessário
    • Identifica o contexto no qual ocorreu um evento. A origem + ID deve ser exclusiva para cada evento. Atualmente, esse campo é sempre enviado como \/ em eventos transmitidos pelo SQL.
  • id

    • Tipo de dados: Cadeia
    • Atributo CloudEvent necessário
    • Identifica o evento. Os produtores devem garantir que a origem + ID seja exclusiva para cada evento distinto. Se um evento duplicado for ressentido (por exemplo, devido a um erro de rede), ele poderá ter a mesma ID. Os consumidores podem assumir que eventos com origem e ID idênticas são duplicados.
  • logicalid

    • Tipo de dados: Cadeia
    • Atributo de extensão
    • As mensagens divididas (devido às restrições de tamanho msg dos Hubs de Eventos) são identificadas por IDs lógicas compartilhadas.
  • time

    • Tipo de dados: Carimbo de data/hora
    • Atributo CloudEvent opcional
    • Carimbo de tempo UTC de quando o commit ocorreu dentro de uma transação SQL que originalmente dispara um evento transmitido.
  • datacontenttype

    • Tipo de dados: Cadeia
    • Atributo CloudEvent opcional
    • Tipo de conteúdo de valor de dados. Esse atributo permite que os dados carreguem qualquer tipo de conteúdo, pelo qual o formato e a codificação podem ser diferentes do formato de evento escolhido. Por exemplo, um evento renderizado usando o formato de envelope JSON pode carregar uma carga XML nos dados e o consumidor é informado por esse atributo que está sendo definido como "application/xml". As regras de como o conteúdo dos dados é renderizado para diferentes datacontenttype valores são definidas nas especificações do formato de evento
  • operation

    • Tipo de dados: Cadeia
    • Extensão
    • Representa o tipo de operação SQL que aconteceu:
      • INS para inserts
      • Atualização para atualizações
      • DEL para deleções
  • segmentindex

    • Tipo de dados: Inteiro
    • Atributo de extensão
    • Índice de segmento, que indica a posição da mensagem dentro dos blocos de mensagem lógica. O índice de segmento fornece informações sobre onde a mensagem está na sequência de fragmentos de mensagem lógica. Esse campo está sempre presente. Use logicalid + segmentindex + campos finalsegment para ordenar os eventos recebidos que representam uma grande carga útil SQL dividida em múltiplos eventos.
  • finalsegment

    • Tipo de dados: Booleano
    • Atributo de extensão
    • Informa se esse segmento é o segmento final da sequência. Esse campo está sempre presente e ajuda a identificar se um evento SQL que era grande demais para o tamanho máximo de mensagem configurado foi dividido em subeventos.
  • data

    • Tipo de dados: Cadeia
    • Atributo CloudEvent opcional
    • Dados de evento específicos do domínio. Para CES, os dados são uma cadeia de caracteres que pode ser analisada como JSON. Este JSON descreve como os dados foram alterados. O formato do atributo de dados está no formato de atributo Data.

Exemplos

Exemplo de mensagem JSON – inserir

{
  "specversion": "1.0",
  "type": "com.microsoft.SQL.CES.DML.V1",
  "source": "\/",
  "id": "d43f09a6-d13b-4902-86d4-17bdb5edb872",
  "logicalid": "9c8d4ad2-bf54-4f10-a96f-038af496997f:0000002C00000300017C:00000000000000000001",
  "time": "2025-03-14T16:45:20.650Z",
  "datacontenttype": "application\/json",
  "operation": "INS",
  "splitindex": 0,
  "splittotalcnt": 0,
  "data": "{\n  \"eventsource\": {\n    \"db\": \"db1\",\n    \"schema\": \"dbo\",\n    \"tbl\": \"Purchases\",\n    \"cols\": [\n      {\n        \"name\": \"purchase_id\",\n        \"type\": \"int\",\n        \"index\": 0\n      },\n      {\n        \"name\": \"customer_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 1\n      },\n      {\n        \"name\": \"product_id\",\n        \"type\": \"int\",\n        \"index\": 2\n      },\n      {\n        \"name\": \"product_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 3\n      },\n      {\n        \"name\": \"price_per_item\",\n        \"type\": \"int\",\n        \"index\": 4\n      },\n      {\n        \"name\": \"quantity\",\n        \"type\": \"int\",\n        \"index\": 5\n      },\n      {\n        \"name\": \"purchase_date\",\n        \"type\": \"datetime\",\n        \"index\": 6\n      },\n      {\n        \"name\": \"payment_method\",\n        \"type\": \"varchar(50)\",\n        \"index\": 7\n      }\n    ],\n    \"pkkey\": [\n      {\n        \"columnname\": \"purchase_id\",\n        \"value\": \"105\"\n      }\n    ]\n  },\n  \"eventrow\": {\n    \"old\": \"{}\",\n    \"current\": \"{\\\"purchase_id\\\": \\\"105\\\", \\\"customer_name\\\": \\\"Anna Doe\\\", \\\"product_id\\\": \\\"101\\\", \\\"product_name\\\": \\\"Game 2077\\\", \\\"price_per_item\\\": \\\"60\\\", \\\"quantity\\\": \\\"1\\\", \\\"purchase_date\\\": \\\"2025-03-14 16:45:01.000\\\", \\\"payment_method\\\": \\\"Credit Card\\\"}\"\n  }\n}"
}

Exemplo de mensagem JSON – atualizado

{
  "specversion": "1.0",
  "type": "com.microsoft.SQL.CES.DML.V1",
  "source": "\/",
  "id": "c425575f-00bb-45cf-acec-c55fdc7d08cd",
  "logicalid": "9c8d4ad2-bf54-4f10-a96f-038af496997f:0000002C000003500004:00000000000000000001",
  "time": "2025-03-14T16:49:59.567Z",
  "datacontenttype": "application\/json",
  "operation": "UPD",
  "splitindex": 0,
  "splittotalcnt": 0,
  "data": "{\n  \"eventsource\": {\n    \"db\": \"db1\",\n    \"schema\": \"dbo\",\n    \"tbl\": \"Purchases\",\n    \"cols\": [\n      {\n        \"name\": \"purchase_id\",\n        \"type\": \"int\",\n        \"index\": 0\n      },\n      {\n        \"name\": \"customer_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 1\n      },\n      {\n        \"name\": \"product_id\",\n        \"type\": \"int\",\n        \"index\": 2\n      },\n      {\n        \"name\": \"product_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 3\n      },\n      {\n        \"name\": \"price_per_item\",\n        \"type\": \"int\",\n        \"index\": 4\n      },\n      {\n        \"name\": \"quantity\",\n        \"type\": \"int\",\n        \"index\": 5\n      },\n      {\n        \"name\": \"purchase_date\",\n        \"type\": \"datetime\",\n        \"index\": 6\n      },\n      {\n        \"name\": \"payment_method\",\n        \"type\": \"varchar(50)\",\n        \"index\": 7\n      }\n    ],\n    \"pkkey\": [\n      {\n        \"columnname\": \"purchase_id\",\n        \"value\": \"105\"\n      }\n    ]\n  },\n  \"eventrow\": {\n    \"old\": \"{}\",\n    \"current\": \"{\\\"purchase_id\\\": \\\"105\\\", \\\"customer_name\\\": \\\"Anna Doe\\\", \\\"product_id\\\": \\\"100\\\", \\\"product_name\\\": \\\"Game 2066\\\", \\\"price_per_item\\\": \\\"50\\\", \\\"quantity\\\": \\\"2\\\", \\\"purchase_date\\\": \\\"2025-03-14 16:45:01.000\\\", \\\"payment_method\\\": \\\"Credit Card\\\"}\"\n  }\n}"
}

Exemplo de mensagem JSON – excluir

{
  "specversion": "1.0",
  "type": "com.microsoft.SQL.CES.DML.V1",
  "source": "\/",
  "id": "24fa0c2c-c45d-4abf-9a8d-fba04c29fc86",
  "logicalid": "9c8d4ad2-bf54-4f10-a96f-038af496997f:0000002C000003600019:00000000000000000001",
  "time": "2025-03-14T16:51:39.613Z",
  "datacontenttype": "application\/json",
  "operation": "DEL",
  "splitindex": 0,
  "splittotalcnt": 0,
  "data": "{\n  \"eventsource\": {\n    \"db\": \"db1\",\n    \"schema\": \"dbo\",\n    \"tbl\": \"Purchases\",\n    \"cols\": [\n      {\n        \"name\": \"purchase_id\",\n        \"type\": \"int\",\n        \"index\": 0\n      },\n      {\n        \"name\": \"customer_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 1\n      },\n      {\n        \"name\": \"product_id\",\n        \"type\": \"int\",\n        \"index\": 2\n      },\n      {\n        \"name\": \"product_name\",\n        \"type\": \"varchar(100)\",\n        \"index\": 3\n      },\n      {\n        \"name\": \"price_per_item\",\n        \"type\": \"int\",\n        \"index\": 4\n      },\n      {\n        \"name\": \"quantity\",\n        \"type\": \"int\",\n        \"index\": 5\n      },\n      {\n        \"name\": \"purchase_date\",\n        \"type\": \"datetime\",\n        \"index\": 6\n      },\n      {\n        \"name\": \"payment_method\",\n        \"type\": \"varchar(50)\",\n        \"index\": 7\n      }\n    ],\n    \"pkkey\": [\n      {\n        \"columnname\": \"purchase_id\",\n        \"value\": \"105\"\n      }\n    ]\n  },\n  \"eventrow\": {\n    \"old\": \"{\\\"purchase_id\\\": \\\"105\\\", \\\"customer_name\\\": \\\"Anna Doe\\\", \\\"product_id\\\": \\\"100\\\", \\\"product_name\\\": \\\"Game 2066\\\", \\\"price_per_item\\\": \\\"50\\\", \\\"quantity\\\": \\\"2\\\", \\\"purchase_date\\\": \\\"2025-03-14 16:45:01.000\\\", \\\"payment_method\\\": \\\"Credit Card\\\"}\",\n    \"current\": \"{}\"\n  }\n}"
}

Formato de atributo de dados

Os dados são um objeto JSON encapsulado no atributo de cadeia de caracteres que contém dois atributos:

  • eventSource
  • eventRow
"data": "{ "eventsource": {<eventSource>}, "eventdata": {<eventData>}}"

Os detalhes desses dois atributos são explicados com mais detalhes nas seguintes seções:

eventsource

Descreve os metadados sobre o banco de dados e a tabela em que o evento ocorreu:

  • db

    • Tipo de dados: Cadeia
    • Descrição: o nome do banco de dados em que a tabela está localizada.
    • Exemplo: cessqldb001
  • schema

    • Tipo de dados: Cadeia
    • Descrição: o esquema de banco de dados que contém a tabela.
    • Exemplo: dbo
  • tbl

    • Tipo de dados: Cadeia
    • Descrição: a tabela na qual o evento ocorreu.
    • Exemplo: Purchases
  • cols

    • Tipo de dados: Matriz
    • Descrição: uma matriz que detalha as colunas na tabela.
      • nome (cadeia de caracteres): o nome da coluna.
      • tipo (cadeia de caracteres): o tipo de dados da coluna (VARCHAR ou INT).
      • índice (inteiro): o índice ou a posição da coluna na tabela.
  • pkkey

    • Tipo de dados: Matriz
    • Descrição: representa as colunas de chave primária e seus valores para identificar a linha específica.
      • columnname (cadeia de caracteres): o nome da coluna usada na chave primária.
      • value (string/int/etc.): o valor da coluna usada na chave primária ajuda a identificar exclusivamente a linha.

eventrow

Descreve as alterações no nível de linha e compara os valores antigos e atuais dos campos no registro.

  • old (objeto encapsulado em cadeia de caracteres): representa os valores na linha antes do evento.
    • Cada par chave-valor consiste em:
      • <column_name>: (cadeia de caracteres): o nome da coluna.
      • <column_value>: (string/int/etc.): o valor anterior para essa coluna.
  • current (objeto encapsulado em cadeia de caracteres): representa os valores atualizados na linha após o evento.
    • Semelhante ao objeto antigo, com cada par chave-valor estruturado como:
      • <column_name> (cadeia de caracteres): o nome da coluna.
      • <column_value> (string/int/etc.): o valor novo ou atual para essa coluna.

Esquema JSON do CES CloudEvent

{
  "type": "record",
  "name": "ChangeEvent",
  "fields": [
    {
      "name": "specversion",
      "type": "string"
    },
    {
      "name": "type",
      "type": "string"
    },
    {
      "name": "source",
      "type": "string"
    },
    {
      "name": "id",
      "type": "string"
    },
    {
      "name": "logicalid",
      "type": "string"
    },
    {
      "name": "time",
      "type": "string"
    },
    {
      "name": "datacontenttype",
      "type": "string"
    },
    {
      "name": "operation",
      "type": "string"
    },
    {
      "name": "segmentindex",
      "type": "int"
    },
    {
      "name": "finalsegment",
      "type": "boolean"
    },
    {
      "name": "data",
      "type": "bytes"
    }
  ]
}

Esquema JSON do atributo de dados CES

{
  "name": "Data",
  "type": "record",
  "fields": [
    {
      "name": "eventsource",
      "type": {
        "name": "EventSource",
        "type": "record",
        "fields": [
          {
            "name": "db",
            "type": "string"
          },
          {
            "name": "schema",
            "type": "string"
          },
          {
            "name": "tbl",
            "type": "string"
          },
          {
            "name": "cols",
            "type": {
              "type": "array",
              "items": {
                "name": "Column",
                "type": "record",
                "fields": [
                  {
                    "name": "name",
                    "type": "string"
                  },
                  {
                    "name": "type",
                    "type": "string"
                  },
                  {
                    "name": "index",
                    "type": "int"
                  }
                ]
              }
            }
          },
          {
            "name": "pkkey",
            "type": {
              "type": "array",
              "items": {
                "name": "PkKey",
                "type": "record",
                "fields": [
                  {
                    "name": "columnname",
                    "type": "string"
                  },
                  {
                    "name": "value",
                    "type": "string"
                  }
                ]
              }
            }
          },
          {
            "name": "transaction",
            "type": {
              "name": "Transaction",
              "type": "record",
              "fields": [
                {
                  "name": "commitlsn",
                  "type": "string"
                },
                {
                  "name": "beginlsn",
                  "type": "string"
                },
                {
                  "name": "sequencenumber",
                  "type": "int"
                },
                {
                  "name": "committime",
                  "type": "string"
                }
              ]
            }
          }
        ]
      }
    },
    {
      "name": "eventrow",
      "type": {
        "name": "EventRow",
        "type": "record",
        "fields": [
          {
            "name": "old",
            "type": "string"
          },
          {
            "name": "current",
            "type": "string"
          }
        ]
      }
    }
  ]
}