FHEM Forum

FHEM => Codeschnipsel => Thema gestartet von: Hadl am 14 April 2023, 15:47:05

Titel: Script zum reparieren einer Sqlite DB nach "database disk image is malformed"
Beitrag von: Hadl am 14 April 2023, 15:47:05
Hallo zusammen,
ich hatte immer mal wieder das Problem, das auf meinem Raspi die Sqlite Datenbank vom logdb defekt wird.
Ich bin mir nicht sicher woran das genau liegt, evtl. geht die Lebensdauer meiner SD Karte zu Ende.
Mit ner neuen SD Karte wurde es aber eher schlimmer, daher nehme ich wieder die ältere. Aber nun genug zum Hintergrund.

Meine Datenbank hat schon einige Jahre Daten an Board, und ist auch schön ca. 50GB groß, mit 128GB SD Karte reicht der Platz aber nicht um sie lokal doppelt zu haben, daher kommt mein NAS hier als Backup und zwischenspeicher zum Einsatz.
Da das ganze für den Raspi und das Netzwerk bei der Datenmenge ca. 1 Tag braucht, aber ich keine Daten verlieren will, kommt eine zwischenspeicher DB währenddessen zum Einsatz.

Ein Verzeichnis im NAS hab ich hierhin gemounted: "/mnt/nas/Sicherung/"

Das Reparieren macht grob folgende Schritte

#!/bin/bash
TIMESTAMP=$(date -d "today" +"%Y%m%d_%H%M%S")
SOURCE_DB="fhem.db"
TARGET_DB="fhem_new.db"

NAS_PATH="/mnt/nas/Sicherung/"

BACKUP_SQL="$NAS_PATH/${TIMESTAMP}_fhem_backup.sql"
BACKUP_DB="$NAS_PATH/${TIMESTAMP}_fhem_backup.db"

echo $TIMESTAMP

if [ ! -f "$SOURCE_DB" ]; then
echo "$SOURCE_DB does not exist"
exit
fi

/etc/init.d/fhem stop

# Create an empty Database with just the schema, to allow fhem to log data into while running the backup and repair.
rm -f empty.db
sqlite3 $SOURCE_DB .schema | sqlite3 empty.db

# Loop through all files (*.db, *.db-shm, *.db-wal) that are existing with the db name in the folder, and rename them.
for i in $( ls ${SOURCE_DB}* ); do
mv $i ${TIMESTAMP}_${i};
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }
done

# Copy empty Database onto the source place, as temporary storage while the database bakup and repair is running.
mv empty.db $SOURCE_DB
chmod 777 $SOURCE_DB

# Start fhem with empty database
/etc/init.d/fhem start

# Pause
#read -n 1 -s

echo "Dump the Database ${TIMESTAMP}_$SOURCE_DB to the SQL Backup on NAS $BACKUP_SQL"
sqlite3 ${TIMESTAMP}_$SOURCE_DB .dump > $BACKUP_SQL
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }

echo "Move the main Database  ${TIMESTAMP}_${SOURCE_DB}* to NAS $NAS_PATH"
for i in $( ls ${TIMESTAMP}_${SOURCE_DB}* ); do
mv ${i} $NAS_PATH
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }
done
rm -f $TARGET_DB
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }
echo "Restore the Database $TARGET_DB from the SQL Backup $BACKUP_SQL"
#cat $BACKUP_SQL | sed -e 's/\(\(BEGIN TRANSACTION;\)\|\(COMMIT;\)\)//g' | sqlite3 $TARGET_DB
sqlite3 $TARGET_DB ".read $BACKUP_SQL"
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }


echo "Add the temporary database $SOURCE_DB entries into the restored one $TARGET_DB"
/etc/init.d/fhem stop
sqlite3 $SOURCE_DB .dump | sqlite3 $TARGET_DB

echo "Now move the merged database back to the source place. Keep copy of temporary database"
for i in $( ls ${SOURCE_DB}* ); do
mv $i ${TIMESTAMP}_temp_${i};
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }
done

echo "Place the merged database back on the source place"
mv $TARGET_DB $SOURCE_DB;
exitStat=$?
test $exitStat -eq 0 && echo "No error! Worked fine" || { echo "There was some error with Code $exitStat"; exit $exitStat; }

chmod 777 $SOURCE_DB

/etc/init.d/fhem start


Ich hoffe das hilft den ein oder anderen von euch seine Datenbank zu reparieren. Kommentare und Verbesserungen sind immer willkommen.