Modul 93_DbRep - Reporting und Management von Datenbankinhalten (DbLog)

Begonnen von DS_Starter, 19 Mai 2016, 22:52:13

Vorheriges Thema - Nächstes Thema

DS_Starter

#735
Hallo Thowe,

bin zur Zeit unterwegs und kann nur kurz antworten. Deswegen vllt. erstmal auf diese Fragen ..

ZitatNoch eine Frage: Ist die writeToDB-Opperation bei Eintritt in die Exitfunktion abgeschlossen, bzw. würde in der Exitfunktion eine Operation auf einer asynchronen DB-Instanz erst nach dem writeToDB-Zugriff ausgeführt werden?

Die writeToDB-Opperation wird _immer_ sofort ausgeführt, unabhängig davon wie das DbLog-Device eingestellt ist. D.H. wenn Exitfunktion ausgeführt wird (bei der Generierung eines jeden Readings), ist die writeToDB-Opperation abgeschlossen.

Zitat
Ich bekomme im Ablauf von mehreren aufeinander abfolgenden DB-Operation mit dbrep mitunter:
Code: [Auswählen]

WARNING - old process nnnn will be killed now to start a new BlockingCall

Kann das zu Datenverlust führen?

Jein.  Wenn es sich um lesende Operationen handelt passiert nichts. Sollte es sich dabei um Schreiboperationen handeln wäre es nicht so gut. Allerdings gibt es dafür prinzipiell eine einfache Lösung.
Grundsätzlich sind das Zeitprobleme, d.h. die eine Operation ist noch nicht abgeschlossen, aber eine weitere sol beginnen ... und zwar mit dem gleichen DbRep-Device ! (Eine Folge der Forderung dass nur ein BlockingCall für ein Device laufen soll)
In solchen Fällen lege dir mehrere DbReps an (copy und dann einstellen) und führe die jeweiligen Operationen auf getrennten Reps aus. Dann hast du das Problem nicht.

Zitat
Das Problem ist letztendlich hausgemacht: Ich muss über ein identisches Device/reading mit gleicher Aggregation aber unterschiedlichen Zeitbereichen in der DB unterscheidbare Einträge erzeugen, Beispiel: Monatsertrag und Vergleichsmonatsertrag.

Hmm.... auf den ersten Blick nicht ganz so simpel. Das bringt mich auf die Idee noch eine Abhängigkeit des resultierenden Readingnamens in der writeToDB-Opperation vom Attribut ReadingNameMap zu berücksichtigen. Dann wäre die Unterscheidung in Fällen die du gerade beschrieben hast recht einfach umzusetzen.
Das kann ich mir aber erst genauer anschauen wenn mein Kurzurlaub vorbei ist  ;)

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

stera

Hallo,

gibt es irgendwo die Möglichkeit eine "0" zu setzen anstatt "-", wenn kein Werte vorliegen? Das bereitete mir gerade Probleme bei den Differenz-Berechnungen vom Gaszähler.

Ansonsten muss ich das nochmal umprogrammieren im Notify oder Userreadings.

Gruß,
SteRa





DS_Starter

#737
Hallo Stera,

nein, wenn keine Werte vorliegen wird absichtlich nicht 0 ausgegeben weil es sonst vorgaukelt es wären Werte vorhanden, die aber eben 0 sind.
Um das konsequent abzugrenzen wird in dem Fall - statt 0 ausgegeben.

Edit: wäre aber über ein Attr machbar wenn es sinnvoll wäre diese Änderung einzubauen.

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Thowe

Hallo Heiko,
die Lösung mit der Übernahme des ReadingNameMap für writeToDB wäre super. Halte ich im Übrigen für konsequent, weil im Event das Mapping übernommen wird.

BTW: Ich könnte bei attr <name> timeDiffToNow auch noch gut ein "Y:1" benötigen. Vorteil ggü. "d:365" wäre, dass unabhängig vom Schaltjahr immer mit dem selben Datum im Monat gerechnet wird. Das könnte für den Monat Februar auch bei "M:1" einsetzbar sein. 

Viele Grüße,
Thowe

DS_Starter

Hallo Thowe,

Ok, ReadingNameMap baue ich dort noch mit rein.
Die Zeitenrechnug mit Year hatte ich noch auf der Agenda. Es fehlt ja auch noch die Jahresaggregation.
Ich hatte das wegen der Schaltjahrproblematik vor mir hergeschoben.  ;)

Melde mich wieder ...

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Thowe

Hallo Heiko,

Danke für die Antworten. Konzentriere Dich erst einmal auf Deinen Urlaub, die Ideen werden bestimmt nicht weniger...
Z.B. Jahresaggregation: Ich erzeuge mir täglich mit timeDiffToNow einen Jahreswert für Summe von Kosten, Energieaufnahme, etc. beginnend 365 Tage vor bis zum laufenden Tag. Lässt sich dieser Wert für alle Tage in einem vorgebbaren Bereich "out-of-theBox" berechnen? Bislang habe ich jedes mal solche Daten extern berechnet und anschließend importiert.
Viele Grüße,
Thowe

DS_Starter

Hallo Thowe,

mit der V7.17.3 im ersten Beitrag kann man nun bei "writeToDB" den Readingnamen mit dem Attribut "readingNameMap" übersteuern.
Die andere Sache mit der Zeitenrechnung braucht etwas mehr Arbeit, Zeit und Test.
Da der Urlaub bald richtig losgeht  :D ... nehme ich mir das für die Zeit danach vor.

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

DS_Starter

Hallo zuammen,

im ersten Beitrag ist die 7.18.0 hinterlegt.
Neben kleineren Bugfixes kann man mit dieser Version in den Attributen timeDiffToNow, timeOlderThan auch dynamisch Jahre angeben in der Form y:<Zahl>.

Beispiel:

attr name timeDiffToNow y:1 h:2.5
# die Startzeit wird auf "aktuelle Zeit - 1 Jahr und 2,5 Stunden" gesetzt
                        
attr name timeDiffToNow y:1.5
# die Startzeit wird auf "aktuelle Zeit - 1,5 Jahre gesetzt

Grüße
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

JoeALLb

Hallo Heiko, @All.

Wie im Thread DbLog besprochen, anbei ein Vorschlag, wie die Partitionierung der MySQL-Tabelle zur verbesserung der Lösch-Performance führen kann.

Anbei ein Tabellenlayout, das die Daten nach Wochentage und anschließend noch nach der neuen Spalte "Longterm" partitioniert. (Als Diskussionsgrundlage).
CREATE TABLE `history` (
`TIMESTAMP` DATETIME NOT NULL DEFAULT '0000-00-00 00:00:00',
`DEVICE` VARCHAR(64) NOT NULL DEFAULT '',
`TYPE` VARCHAR(32) NULL DEFAULT NULL,
`EVENT` VARCHAR(512) NULL DEFAULT NULL,
`READING` VARCHAR(64) NOT NULL DEFAULT '',
`VALUE` VARCHAR(32) NULL DEFAULT NULL,
`UNIT` VARCHAR(32) NULL DEFAULT NULL,
`Longterm` TINYINT(4) NOT NULL DEFAULT '0',
PRIMARY KEY (`DEVICE`, `READING`, `TIMESTAMP`, `Longterm`),
INDEX `Reading_Time_Idx` (`READING`, `TIMESTAMP`) USING BTREE
)
COLLATE='latin1_swedish_ci'
PARTITION BY RANGE (WEEKDAY(timestamp))
SUBPARTITION BY HASH (Longterm)
(PARTITION mon VALUES LESS THAN (1)
(SUBPARTITION monNolong ENGINE = Aria,
  SUBPARTITION monLong ENGINE = Aria),
PARTITION tue VALUES LESS THAN (2)
(SUBPARTITION tueNolong ENGINE = Aria,
  SUBPARTITION tueLong ENGINE = Aria),
PARTITION wed VALUES LESS THAN (3)
(SUBPARTITION wedNolong ENGINE = Aria,
  SUBPARTITION wedLong ENGINE = Aria),
PARTITION thu VALUES LESS THAN (4)
(SUBPARTITION thuNolong ENGINE = Aria,
  SUBPARTITION thuLong ENGINE = Aria),
PARTITION fri VALUES LESS THAN (5)
(SUBPARTITION friNolong ENGINE = Aria,
  SUBPARTITION friLong ENGINE = Aria),
PARTITION sat VALUES LESS THAN (6)
(SUBPARTITION satNolong ENGINE = Aria,
  SUBPARTITION satLong ENGINE = Aria),
PARTITION sun VALUES LESS THAN (7)
(SUBPARTITION sunNolong ENGINE = Aria,
  SUBPARTITION sunLong ENGINE = Aria)) ;


Diese Tabelle kann so jetzt schon in FHEM verwendet werden, ohne Codeänderung.
(Jedoch können die möglichen Vorteile noch nicht direkt genutzt werden.)
Somit könnte die Codeunterstützung jedoch schritt für schritt einfach ergänzt werden!

Eventuell sollte der default bei Longterm statt 0 auf 1 gesetzt werden.
(Man kann Longterm natürlich auch um die Werte 2,3,4,5, etc. ergänzen, wenn es sinn macht. Zb. analog zum Verbose level.

Beispielszenario:
Ein Insert eines Datenwertes HEUTE würde mit dieser Tabelle in der Partitionstabelle "monNoLong" landen.
Wenn ich Longterm auf 1 setzem landet er in der Partitionstabelle "monLong".

Ich packe also alle Werte, die ich nicht dauerhaft speichern möchte, in die Tabelle "*NoLong" und die anderen in "*Long".
Am Ende des Tages nehme ich die Werte aus der NoLong-Tabelle und berechne daraus meine Stundenmittel, etc.
Anschließend lösche ich sämtliche Daten (fast) verzögerungsfrei über

ALTER TABLE history TRUNCATE PARTITION monNoLong;


Hilfreiche Codeunterstützung wäre dafür meines Erachtens nach (durchaus in dieser Reihenfolge als einzelne Punkte realisierbar):
1# Erlauben des direkten Setzens von Longterm auf definierte Werte über ein DbLogexclude/Include Attribut. 
      ((im Moment mache ich das in MySQL direkt über einen inserttrigger)))
2# Unterstützung der Tabellenkonfiguration (zB über set DbRep updateHistoryTable [no]partition)
3# Unterstutzung der neuen Löschmöglichkeiten in DbRep
4# Erlauben der Umkategorisierung von Daten von NoLong auf Long über das Modul nach gewissen Parametern.


Edit: Fragen, die wir noch festlegen sopllten:
#1 Werden mehr als 2 Aufbewahrungszeiten (Longterm NoLongterm) benötigt? Ich bin mir hier nicht so sicher, denn die Komplexität steigt dadurch enorm.


sG
Joe


FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

DS_Starter

Hi Joe,

danke für den umfangreichen Beitrag.
Ich werde das Thema nicht vergessen, bin nur momentan mit einer größeren Weiterentwicklungen vom SSCam-Modul beschäftigt.
Stelle das Thema erstmal etwas zurück und komme später wieder dazu.

LG,
Heiko
ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

JoeALLb

Hallo Heiko,

danke. Ich nutze es ja schon so und habs deswegen nicht übertrieben eilig ;-)
Du könntest abe rmal, falls es dich interessiert, einfach deine Datenbank umstellen.
Sollte danach noch alles so funktionieren wie zuvor und ich denke so wird die Idee dahinter gleich mal klarer.


sG
Joe
FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

pechnase

Hallo zusammen,

ich hänge meine Frage mal in diesen Thread. Hat aber mit der vorhergehenden Frage nichts zu tun aber es geht um das Modul DbRep.

Ich habe folgendes Problem:
- ich habe eine korrupte SQLite Datenbank mit ca. 600MB
- habe dann mit DbRep ein repairSQLite gemacht. Danach war die DB nur noch ca. 250MB groß und es haben viele Jahresmesswerte gefehlt.
- ich mache jede Nacht mir DbRep ein DB-Backup und bewahre immer 10 Backupdateien auf
- da ich zu spät gemerkt habe, dass an der Datenbank etwas korrupt war, da lief dann auch kein Backup mehr, habe ich auf der reparierten DB weiter geloggt.
- meine Idee war jetzt aus einem noch 'guten' Backup die Readings der Jahresmesswerte zu exportieren und danach wieder in die aktuelle DB einzulesen. Mir ist schon klar, dass mir dann ein paar Tage fehlen, aber eben hoffentlich nicht Monate.
- das Ganze wollte ich auf einem Testsystem erledigen, scheitere jetzt aber daran, ein restore des DB-Backups durchzuführen. Ich habe auf dem Testsystem eine dort vorhandene Db so umbenannt, dass Sie zu dem Db-Backup passt. Entsprechende Einträge in db.conf usw. entsprechend abgeändert. Die Db geht auch in den Zustand 'connected'. Nun wollte ich mit DbRep ein restoreSQLite durchführen, kann den entsprechenden File auch auswählen, aber das restore wird sofort mit der Fehlermeldung:

DBD::SQLite::db sqlite_backup_from_file failed: sqlite_backup_from_file failed with error attempt to write a readonly database at ./FHEM/93_DbRep.pm line 6902

abgebrochen. In raspbian die Dateirechte kontrolliert und die sind richtig. Ich habe auch schon das Attribute allowDeletion 1 gesetzt, was aber nichts geändert hat.
Vielleicht kann man ja tatsächlich nur ein restore auf die DB machen, von der auch das Backup erfolgt ist, wie kann ich dann aber meinen Fall lösen, aus einem Db Backup nur bestimmte readings zu exportieren?

Vielen Dank für einen Tipp
Wolfgang
2 x RPI mit FHEM 5.8 (RPI B+ & RPI 2B) verbunden über FHEM2FHEM
- HM Fensterkontakte, Rauchmelder, Fernbedienung, Schalter
- Optolink (Selbstbau) Vitotronic 200KW2
- 1-wire DS1820 Temp.Sensoren, TX29DT-IT
- CUL (busware), nanoCUL, Jeelink (Nachbau), FHEMduino

DS_Starter

Hallo Wolfgang,

deine Vorgehensweise ist erstmal richtig.

ZitatVielleicht kann man ja tatsächlich nur ein restore auf die DB machen, von der auch das Backup erfolgt ist
Nein, diese Beschränkung gibt es nicht. Aber nimm doch nicht schon eine bestehende DB auf deinem Testsystem, sondern lege dir dort eine neue Datenbank ganz nach Vorschrift mit dem Namen der alten DB (sicherheitshalber) an als wolltest du anfangen mit loggen und setzte dir dann im DbLog DEF den Regex so dass nichts reinläuft und connecte dir dann das DbRep-Device. Dann sollte es kein Problem mit dem Restore geben. Achte darauf das user/group fhem/dialout Schreibrechte besitzen.

Zitatwie kann ich dann aber meinen Fall lösen, aus einem Db Backup nur bestimmte readings zu exportieren?
Wenn die DB läuft beschränkste du mit dem Attribut "reading" auf das was du willst und machst dann einen set ... exportToFile.
Danach dann ein importFromFile auf der Zieldatenbank.

Grüße
Heiko


ESXi@NUC+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

pechnase

Hallo Heiko,

herzlichen Dank für die schnelle Antwort. Bin schon mal froh, dass mein Ansatz richtig war. Werde Deinen Vorschlag mal so nachvollziehen. Vielleicht hat sich ja durch Verwendung einer schon vorhandenen DB irgend etwas 'verhakt'.

VG Wolfgang
2 x RPI mit FHEM 5.8 (RPI B+ & RPI 2B) verbunden über FHEM2FHEM
- HM Fensterkontakte, Rauchmelder, Fernbedienung, Schalter
- Optolink (Selbstbau) Vitotronic 200KW2
- 1-wire DS1820 Temp.Sensoren, TX29DT-IT
- CUL (busware), nanoCUL, Jeelink (Nachbau), FHEMduino

pechnase

Hallo Heiko,
ich muss diesen Thread leider nochmals 'aufwärmen'. DbRep Version 7.18.1
Ich habe jetzt, wie von Dir beschrieben, eine neue Datenbank mit gleichem Namen angelegt. In das gleiche Verzeichnis das Backup kopiert und dann mit DbRep mit folgender Konfiguration ein restoreSQLite versucht:


defmod RestoreDbWhng3 DbRep dblog_test_whng3
attr RestoreDbWhng3 dumpDirLocal /opt/fhem/db_recover_whng3/
attr RestoreDbWhng3 dumpFilesKeep 6
attr RestoreDbWhng3 executeAfterProc { fhem("set dblog_test_whng3 reopen");;;;my $duration = ReadingsVal("RestoreDbWhng3","background_processing_time"," ");;;; exmail('test1@xxxxx.de','Restore DB Ende','Restore DB wurde nach ' .$duration. ' sec. beendet') }
attr RestoreDbWhng3 executeBeforeProc { fhem("set dblog_test_whng3 reopen 7200");;;;exmail('test1@xxxxx.de','Restore DB Start','Restore DB wurde gestartet') }
attr RestoreDbWhng3 room DB,Server
attr RestoreDbWhng3 showproctime 1
attr RestoreDbWhng3 verbose 5

setstate RestoreDbWhng3 error
setstate RestoreDbWhng3 2018-06-23 12:00:09 errortext DBD::SQLite::db sqlite_backup_from_file failed: sqlite_backup_from_file failed with error attempt to write a readonly database at ./FHEM/93_DbRep.pm line 6902.\

setstate RestoreDbWhng3 2018-06-23 12:00:09 state error



Die Dateirechte in raspbian sehen folgendermaßen für das Verzeichnis so aus:


drwxr-xr-x  2 fhem dialout    4096 Jun 23 12:00 db_recover_whng3


und für die Dateien so:

-rwxrwxrwx 1 fhem dialout 632127488 Jun 22 18:40 fhem_2018_06_07_00_39.sqlitebkp
-rw-rw-rw- 1 fhem dialout      4096 Jun 23 11:58 fhem.db
-rwxrwxrwx 1 fhem dialout 168099840 Jun 22 20:28 fhem.db.saved


Aus meiner Sicht sind die so 'ausreichend'. Leider wird das restore nicht ausgeführt und mit der Fehlermeldung, siehe oben abgebrochen. Im Log steht auch mit Verbose 5 nicht mehr drin.

Wie könnte ich mich dem Problem noch nähern?

Danke für Deine Unterstützung

Viele Grüße
Wolfgang
2 x RPI mit FHEM 5.8 (RPI B+ & RPI 2B) verbunden über FHEM2FHEM
- HM Fensterkontakte, Rauchmelder, Fernbedienung, Schalter
- Optolink (Selbstbau) Vitotronic 200KW2
- 1-wire DS1820 Temp.Sensoren, TX29DT-IT
- CUL (busware), nanoCUL, Jeelink (Nachbau), FHEMduino