SQLite Database ist corrupt - wie kann ich analysieren?

Hi Zusammen,

bitte nicht steinigen wenn ich im falschen Forum poste, das ist meine erste Frage hier.

In letzter Zeit habe ich immer wieder (habe festgestellt, dass morgens gegen 5 Uhr) den Fall, dass die Datenbank home-assistant_v2.db neu erstellt wird - und eine Datei mit dem Namen: “home-assistant_v2.db.corrupt.2024-01-17T05:07:34.790455+00:00” neben dran liegt. In den Logs konnte ich dann heute morgen folgendes feststellen:

2024-01-17 10:06:40.404 WARNING (Recorder) [homeassistant.components.recorder.util] The system could not validate that the sqlite3 database at //config/home-assistant_v2.db was shutdown cleanly
2024-01-17 10:06:40.532 WARNING (Recorder) [homeassistant.components.recorder.util] Ended unfinished session (id=2 from 2024-01-16 18:33:41.837431)

sowie:

2024-01-17 09:46:17.310 WARNING (Recorder) [homeassistant.components.sensor.recorder] Entity sensor.rct_power_storage_inverter_energy_production_day from integration rct_power has state class total_increasing, but its state is negative. Triggered by state -144.9 with last_updated set to 2024-01-17T08:44:42.269841+00:00. Please create a bug report at https://github.com/weltenwort/home-assistant-rct-power-integration/issues
2024-01-17 09:46:48.397 WARNING (MainThread) [androidtv.adb_manager.adb_manager_async] Couldn't connect to 192.168.2.121:5555.  ConnectionResetError: Connection reset by peer
2024-01-17 09:47:43.094 ERROR (Recorder) [homeassistant.components.recorder.core] Unrecoverable sqlite3 database corruption detected: (sqlite3.DatabaseError) database disk image is malformed
[SQL: INSERT INTO states (entity_id, state, attributes, event_id, last_changed, last_changed_ts, last_updated, last_updated_ts, old_state_id, attributes_id, context_id, context_user_id, context_parent_id, origin_idx, context_id_bin, context_user_id_bin, context_parent_id_bin, metadata_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING state_id]
[parameters: (None, '2191', None, None, None, None, None, 1705481258.87729, 681305, 11080, None, None, None, 0, <memory at 0x951da3e8>, None, None, 321)]
(Background on this error at: https://sqlalche.me/e/20/4xp6)
Traceback (most recent call last):
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2112, in _exec_insertmany_context
    dialect.do_execute(
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 922, in do_execute
    cursor.execute(statement, parameters)
sqlite3.DatabaseError: database disk image is malformed

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 912, in _process_one_task_or_recover
    return task.run(self)
           ^^^^^^^^^^^^^^
  File "/usr/src/homeassistant/homeassistant/components/recorder/tasks.py", line 305, in run
    instance._commit_event_session_or_retry()
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 1163, in _commit_event_session_or_retry
    self._commit_event_session()
  File "/usr/src/homeassistant/homeassistant/components/recorder/core.py", line 1183, in _commit_event_session
    session.commit()
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 1969, in commit
    trans.commit(_to_root=True)
  File "<string>", line 2, in commit
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
    ret_value = fn(self, *arg, **kw)
                ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 1256, in commit
    self._prepare_impl()
  File "<string>", line 2, in _prepare_impl
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/state_changes.py", line 139, in _go
    ret_value = fn(self, *arg, **kw)
                ^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 1231, in _prepare_impl
    self.session.flush()
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4312, in flush
    self._flush(objects)
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4447, in _flush
    with util.safe_reraise():
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/util/langhelpers.py", line 146, in __exit__
    raise exc_value.with_traceback(exc_tb)
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/session.py", line 4408, in _flush
    flush_context.execute()
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 463, in execute
    n.execute_aggregate(self, set_)
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/unitofwork.py", line 759, in execute_aggregate
    persistence.save_obj(
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/persistence.py", line 93, in save_obj
    _emit_insert_statements(
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/orm/persistence.py", line 1136, in _emit_insert_statements
    result = connection.execute(
             ^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1416, in execute
    return meth(
           ^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/sql/elements.py", line 516, in _execute_on_connection
    return connection._execute_clauseelement(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1639, in _execute_clauseelement
    ret = self._execute_context(
          ^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 1843, in _execute_context
    return self._exec_insertmany_context(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2120, in _exec_insertmany_context
    self._handle_dbapi_exception(
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2343, in _handle_dbapi_exception
    raise sqlalchemy_exception.with_traceback(exc_info[2]) from e
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/base.py", line 2112, in _exec_insertmany_context
    dialect.do_execute(
  File "/usr/local/lib/python3.11/site-packages/sqlalchemy/engine/default.py", line 922, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.DatabaseError: (sqlite3.DatabaseError) database disk image is malformed
[SQL: INSERT INTO states (entity_id, state, attributes, event_id, last_changed, last_changed_ts, last_updated, last_updated_ts, old_state_id, attributes_id, context_id, context_user_id, context_parent_id, origin_idx, context_id_bin, context_user_id_bin, context_parent_id_bin, metadata_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) RETURNING state_id]
[parameters: (None, '2191', None, None, None, None, None, 1705481258.87729, 681305, 11080, None, None, None, 0, <memory at 0x951da3e8>, None, None, 321)]
(Background on this error at: https://sqlalche.me/e/20/4xp6)
2024-01-17 09:47:43.887 ERROR (Recorder) [homeassistant.components.recorder.util] The system will rename the corrupt database file //config/home-assistant_v2.db to //config/home-assistant_v2.db.corrupt.2024-01-17T08:47:43.887618+00:00 in order to allow startup to proceed

nach etwas googeln nach der Fehlermeldung konnte ich rausfinden wie man die Datenbank wieder ans Fliegen bekommt:

sqlite3 home-assistant_v2.db “.dump” | sqlite home-assistant_v2.db_fixed

hat leider nichts gebracht. Da habe ich eine leere Datei bekommen (0Kb).
Ich konnte die Datenbank noch retten indem ich sie auf meinem (Windows) Rechner per DbBrowser (SQLite) aufgemacht habe, als .sql file exportiert, neue Datenbank importiert und gespeichert.

Mein System.
Raspberry Pi 4, 4GB
Docker Version von HA
Mounted volume auf eine SSD Karte

Was mich gewundert hat, war dass ich wenn ich die Datenbank per DbBrowser öffne, dass mir nichts auffällt, was da korrupt sein könnte.
Auch dass das einspielen der DB aus dem backup (von 1:30 Uhr) direkt als korrupt verabschiedet wird.

Hat jemand von euch einen Denkanstoß, wie ich rausfinden kann, was welche Entity den korrupten Datenbank Eintrag verursacht, bzw. wo ich ansetzen kann? Weil per DbBrowser konnte ich leider nichts auffälliges entdecken.

Hi,

ich bin mir nicht absolut sicher, aber wenn das regelmäßig oder halt öfters auftritt, solltest du vielleicht die SD-Karte wechseln, am besten gegen eine SSD (Festplatte). Kann sein das die Karte die Biege macht, sich das aber nur in Fragmenten beim Lesen oder Speichern äußert.

ich habe die Daten bereits auf einer SSD Karte ausgelagert.
Ich werde die Tage allerdings mal die SSD formatieren und auch das OS meines PIs neu installieren und hoffen dass das einen Erfolg bringt

Wenn du von einer SSD-Karte schreibst, meinst du damit eine SD-Karte


oder eine SSD?

Hi, ja mir ist schon bewusst was eine SSD ist.
Ich habe das Betriebsystem auf einer SD Karte (dort wo auch der Docker deamon läuft) und die Daten (also das mounted config verzeichnis von HomeAssistant) auf einer SSD, die per USB 3 an den PI angeschlossen ist.

Sorry wenn sich das besserwisserisch liest, aber ein Begriff wie SSD-Karte klingt verwirrend. :wink: Ist aber jetzt die Frage ob die SD-Karte defekt ist oder die SSD, bzw. ob es per USB Schreibprobleme gibt. Dafür kenne ich mich mit Raspi’s nicht genug aus.

Ah ja, jetzt verstehe ich es, warum du da so drauf rumgeritten bist.
Ich hatte da wohl gleichzeitig schreiben wollen: SD Karte OS installiert und Daten auf der SSD Festplatte - und dann kommt halt eine SSD Karte raus :smiley:

Problem besteht weiterhin, allerdings habe ich mittlerweile eine Lösung im Kopf, wie sich das System selbst heilen kann - indem ich einen Command_line Sensor installiert habe, der die Size der Datenbank testet und wenn die kleiner als 15MB ist, einen Alert schickt und den Selbsthealing process anstößt. Dazu verwende ich die .recover Funktion von SQLite3.

Sobald ich Zeit habe und das Betriebssystem auf 64Bit hochgedreht habe, kann ich berichten. Ansonsten wird es vermutlich an der SSD liegen, weil ich habe schon gesehen, dass die Read/Write Permission auf die Platte weg ist. Vielleicht liegt es an der Stromversorgung - vielleicht ist die Platte einfach kapuut. Ist halt per USB und externes Gehäuse angeschhlossen.

Ich halte euch auf dem Laufenden, was es dann letztendlich war.

Was jetzt genau der Fehler war kann ich im Nachgang nicht mehr bewerten.
Was ich zuletzt allerdings gemacht habe ist folgendes:

  1. Die Festplatte neu platziert, so dass sie völlig frei von Vibration ist, um auszuschließen, dass das Thema durch disconnects aufgrund von kleinen Erschütterungen kam
  2. Nochmal separat einen Export/Import mit der funktonierenden Datenbank gemacht über die Software DB Browser (SQLite) - das hat dazu geführt, dass die Datenbankgröße plötzlich von etwa 700 MB auf 250 MB runter gefallen ist
  3. eine USV installiert, und den raspberry pi dran gehängt, um kurzfristige Stromunterbrechungen oder Spannungspeaks auszuschließen

für das Monitoring habe ich folgendes gemacht:

  1. commandline sensor, welcher alle 30 sekunden die Datenbankgröße lädt. Sobald die Größe unter 50MB (wollte ienen Schwellenwert zu 0 haben) fällt, habe ich eine push notification an mein handy geshcickt, um direkt reagieren zu könnnen und die Datenbank per SQLite Recovery Befehl wieder herzustellen.

Thats it, also leider keine Lösung gefunden die reproduzierbar, bzw. gesichert ist, aber ich vermute einfach, dass es um Disconnects der Festplatte ging, sei es jetzt aufgrund von Leistungsschwäche (weil die Festplatte nur am PI, aber nicht an eine externe Stromversorgung angeschlossen ist). oder aufgrund von Leistungsspitzen im generellen Hausnetz .
Eventuell war es auch eine fehlerhafte Integration die ich installiert habe und sich gefixt hat - da ich da aber aufgrund von Langzeitdaten nicht auf die Backups vertrauen konnte, habe ich hier die Suche komplett eingestellt

Neuinstalliert und auf die 64 Bit version des Pi OS bin ich nicht gewechselt, und neu formatierung der Festplatte habe ich beides jetzt noch nicht ausproviert, das wären aber noch die weiteren Punkte, die bei mir auf der Agenda standen.