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\"}"]
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.
Hilfreichster Kommentar
So sieht es jetzt mit temp fix aus: