Cardano-db-sync: Ausnahme wegen Unicode auf Testnet

Erstellt am 19. Sept. 2020  ·  15Kommentare  ·  Quelle: input-output-hk/cardano-db-sync

Im testnet Netzwerk löst cardano-db-sync bei tags/5.0.0 im extended Modus aufgrund von Unicode-Parsing-/Handhabungsproblemen Ausnahmen bei Block 1816809 aus. Es kann nicht über diesen Block hinaus synchronisiert werden.

[db-sync-node:Info:234667] [2020-09-19 14:23:20.41 UTC] Starting chainSyncClient
[db-sync-node:Info:234667] [2020-09-19 14:23:20.48 UTC] Cardano.Db tip is at slot 6061839, block 1816809
[db-sync-node:Info:234672] [2020-09-19 14:23:20.48 UTC] Running DB thread
[db-sync-node:Info:234672] [2020-09-19 14:23:20.65 UTC] Rolling back to slot 6061839, hash 98414d12d1d1f05210dea6ce4082e1bcbbcfdf56343fd1cb44a8778c4c9ea57a
[db-sync-node:Info:234672] [2020-09-19 14:23:20.66 UTC] Deleting blocks numbered: []
[db-sync-node:Error:234672] [2020-09-19 14:23:21.03 UTC] runDBThread: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node:Error:234667] [2020-09-19 14:23:21.05 UTC] ChainSyncWithBlocksPtcl: DbInsertException "TxMetadata" (SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""})
[db-sync-node.Subscription:Error:234663] [2020-09-19 14:23:21.05 UTC] [String "Application Exception: LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"} DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"})",String "SubscriptionTrace"]
[db-sync-node.ErrorPolicy:Error:4] [2020-09-19 14:23:21.05 UTC] [String "ErrorPolicyUnhandledApplicationException (DbInsertException \"TxMetadata\" (SqlError {sqlState = \"22P05\", sqlExecStatus = FatalError, sqlErrorMsg = \"unsupported Unicode escape sequence\", sqlErrorDetail = \"\\\\u0000 cannot be converted to text.\", sqlErrorHint = \"\"}))",String "ErrorPolicyTrace",String "LocalAddress {getFilePath = \"/run/cardano-node/node.socket\"}"]

Hilfreichster Kommentar

So sieht es jetzt mit temp fix aus:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

Alle 15 Kommentare

Das sind riesige Schmerzen im Nacken.

Die eingefügten TX-Metedaten sind

(1,S "\NUL\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX\ETX")

die als JSON codiert wird:

"\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003"

was natürlich kein gültiges UTF8 ist und daher von der Datenbank abgelehnt wird.

Schlimmer noch, das obige wird wie gezeigt von der Haskell Text Bibliothek als UTF8 codiert, aber PostgreSQL lehnt es dann ab.

Lassen Sie mich wiederholen, was für ein RIESIGER Schmerz im Nacken das ist.

Der fragliche String wird von der Haskell Text Bibliothek in UTF8 dekodiert und dann an Postgres übergeben, das eine SqlError Ausnahme auslöst. Ich habe versucht, diese Ausnahme abzufangen, aber das Abfangen der Ausnahme scheint nicht zu funktionieren.

Ich kann die Ausnahme abfangen und protokollieren:

[db-sync-node:Warning:37] [2020-09-21 00:26:18.77 UTC] insertTxMetadata: Failed to insert (1,S "\NUL...\ETX")
SqlError {sqlState = "22P05", sqlExecStatus = FatalError, sqlErrorMsg
 = "unsupported Unicode escape sequence", sqlErrorDetail = "\\u0000 cannot be converted to text.", sqlErrorHint = ""}

aber dann gibt es noch eine zweite ausnahme:

[db-sync-node:Error:37] [2020-09-21 00:26:18.77 UTC] runDBThread: SqlError {sqlState = "25P02", sqlExecStatus = FatalError, sqlErrorMsg = "current transaction is aborted, commands ignored until end of transaction
 block", sqlErrorDetail = "", sqlErrorHint = ""}

Dies deutet darauf hin, dass ich den JSON vor dem Einfügen vollständiger validieren muss.

Wir können ungültiges UTF8 in PostgreSQL speichern, aber nur als bytea Daten, nicht als jsonb und wenn wir uns für die JSON-Abfrageunterstützung des ehemaligen Postgres entscheiden, ist die Unterstützung nicht verfügbar.

Ich habe eine manuelle UTF8-Decodierung versucht:

decodeUtf8IO :: ByteString -> IO (Either Text.UnicodeException Text)
decodeUtf8IO = try . evaluate . Text.decodeUtf8With Text.strictDecode

und das hat auch das gleiche problem.

Von: https://stackoverflow.com/questions/31671634/handling-unicode-sequences-in-postgresql

Ein Null-Byte ist in einem PostgreSQL-String nicht zulässig. Beides ist kein Nullcodepunkt.

Denke derzeit, dass dies an der Art und Weise liegt, wie Haskell/Persistent dies serialisiert, um es an Postgres zu senden. Derzeit versuchen, diese Theorie zu validieren.

Aeson.encode maskiert bereits das Zeichen NUL zu \u0000 das Persistent dann ablehnt.

Eine ordentliche Lösung dafür zu finden, wird nicht einfach sein.

Ich habe das untersucht und es scheint, dass diese Eigenschaften gelten:

  • "\u0000\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003\u0003" ist ziemlich gültig als UTF-8, da UTF-8 es ermöglicht, \u0000 direkt darzustellen.
  • \u0000 ist für jsonb nicht zulässig, da es nicht in text .

Die einzige temporäre Lösung, um es in JSON und dann in Text zu codieren und dann die fehlerhafte Zeichenfolge zu erkennen und das JSON-Objekt abzulehnen, wenn es die fehlerhafte Sequenz enthält. Ich frage mich auch, ob \u0000 die einzige Sequenz ist, die ich ablehnen muss,

Könnten Sie nicht zwei Spalten speichern? das Bytea und das JSON, wenn es kein Nicht-Text-Zeichen enthält, sodass jeder verwenden kann, was er benötigt.

@erikd Die \u0000 wird hier zusammen mit allen anderen Regeln, die Postgres befolgt, klar angegeben. Fazit: Es gibt Ablehnungen und Transformationen.

Um eine undichte Abstraktion zu vermeiden, müssen die genauen Werte (wie vom Benutzer angegeben) gespeichert werden. Dies bedeutet grob gesagt entweder ein Blob (= keine Struktur in der DB) oder JSON-String-Werte, die irgendwie die ursprüngliche Bedeutung beibehalten: zum Beispiel base64-codierte String-Werte in der DB (also die Wiederherstellung der Struktur auf Kosten einer zusätzlichen Verarbeitung in der Anwendung in um von base64 in den tatsächlichen Wert zu übersetzen).

Der temporäre Workaround-Fix (einfaches Löschen von Metadatenobjekten, die nicht in Postgres eingefügt werden können) wurde mit Master zusammengeführt.

So sieht es jetzt mit temp fix aus:

[db-sync-node:Info:37] [2020-09-22 10:19:09.66 UTC] insertShelleyBlock: epoch 84, slot 6060000, block 1816721, hash 3ec15354c53deae4eb26a206cc3185f799e80bd09393f279bce7e53a7d633144
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.08 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Warning:37] [2020-09-22 10:19:24.10 UTC] insertTxMetadata: dropped due to a Unicode NUL character.
[db-sync-node:Info:37] [2020-09-22 10:19:24.93 UTC] insertShelleyBlock: epoch 84, slot 6065000, block 1816973, hash 0ab0dd5c36c6eb480b8bbd05508be952c5ed8597a4e422af25bd80a905a9368d

Ob Docker repariert ist und was die reparierte Version ist

Es ist nicht behoben, aber 5.0.x (aber ich würde 5.0.2 empfehlen) hat eine Problemumgehung, die dieses Problem vermeidet, indem tx_metadata mit dem Unicode NUL Zeichen entfernt wird.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen