FirebirdSQL
Firebird ist ein SQL-Datenbankserver. Firebird is a registered trademark of the Firebird Foundation [[1]]
Zur Datenhaltung verwendet OrgaMon den freien Datenbank Server Firebird-SQL (http://firebirdsql.org/).
Installation
Im Moment setze ich immer den SuperServer der Version 3 ein.
openSUSE 15.3
zypper addrepo https://download.opensuse.org/repositories/home:mkubecek:firebird30/openSUSE_Leap_15.3/home:mkubecek:firebird30.repo zypper refresh zypper install firebird
OpenSuSE 15.1 / 15.2
zypper install firebird-server firebird-examples telnet
# # Sorge für angepasste Einstellungen # mv /etc/firebird/firebird.conf /etc/firebird/_firebird.conf joe /etc/firebird/firebird.conf
# # Einstellungen für erfolgreiches Konnektieren von 2.5 Clients # AuthServer = Legacy_Auth AuthClient = Legacy_Auth UserManager = Legacy_UserManager AllowEncryptedSecurityDatabase = false WireCrypt = Enabled WireCompression = false RemoteAuxPort = 3051 DatabaseAccess = Restrict /srv/firebird
# # Start the server # systemctl enable firebird.service systemctl start firebird.service # # test if server is running # telnet localhost 3050 # # set the SYSDBA Password, MUST replace *********** # gsec -user sysdba -password masterkey -modify sysdba -pw ~DeinNeuesPasswortHier~ # # Alternativ, aber unklar # isql-fb employee; SQL> create or alter user SYSDBA password '***********'; SQL> commit; SQL> quit;
/etc/crontab
- damit bei einem freigegebenen Share firebird-Datenbanken löschbar sind
# # Firebird # 00 10 * * * root chmod -R 777 /srv/firebird
/etc/samba/smb.conf
- Nehme die Freigabe des Datenbankverzeichnisses zu deinen Samba-Shares hinzu
- Die Arbeitsstationen müssen keinesfalls dieses Share mit einem Laufwerk verbinden
- OrgaMon wird bei der Datensicherung auf \\host\firebird zugreifen
... [firebird] comment = Firebird path = /srv/firebird guest ok = yes writeable = yes create mode = 0777 directory mode = 0777 force create mode = 0777 force directory mode = 0777
selbst compilieren
zypper install libicu-devel libtommath-devel libtomcrypt-devel wget http://web.firebirdsql.org/download/snapshot_builds/linux/fb3.0/Firebird-3.0.5.33221-0.tar.bz2 bunzip2 Firebird-3.0.5.33221-0.tar.bz2 tar -xf Firebird-3.0.5.33221-0.tar cd Firebird-3.0.5.33221-0/ ./configure make make install
- firebird.conf ist in /usr/local/firebird
- gbak: /usr/local/firebird/bin/gbak
- service ist: systemctl status firebird-superserver.service
Raspberry Pi
apt install firebird3.0-server firebird3.0-examples telnet
isql-fb security.db
rpm direkt von firebirdsql
## xinetd muss laufen! chkconfig --add xinetd rcxinetd start ## Dies installiert firebird und startet es (für immer!) rpm -i FirebirdCS-2.0.0.12748-0.nptl.i686.rpm ## man muss noch das passwort notieren cat /opt/firebird/SYSDBA.passwd ## man kann noch definieren, wo die firebird Datenbanken liegen dürfen ## auf alle Fälle muss man verhindern, dass von aussen die security.fdb ## geöffnet werden kann. joe /opt/firebird/firebird.conf DatabaseAccess = Restrict /srv
rpm direkt vom Buildservice OpenSuse
ein manuelles Installieren mit rpm -i firebird- usw. war mir nicht möglich, da ich die Referenz auf "firebird-arch" nicht auflösen konnte (grrr.).
- Nehme im Yast das Build-Repository hinzu: http://download.opensuse.org/repositories/server:/database/openSUSE_13.1/
- Suche und Installiere nun den "firebird-classic"
- Gehe weg vom "default" Passwort für den SYSDBA: gsec -user sysdba -password masterkey -modify sysdba -pw ~DeinNeuesPasswortHier~
- das wars ...
OpenSuSE 13.1
Im Moment setze ich auf SMP Systemen den "Classic Server (CS)" ein. Es bedeutet, es läuft kein einzelner Dämon, sondern pro Verbindung wird ein Server-Prozess neu gestartet (fb_inet_server). Die Synchronisation erfolgt über Datei-Locks der jeweiligen Datenbank-Datei mit Hilfe eines monolitischen Prozesses (fb_lock_mgr). Bei dem Hochstarten der einzelnen Server-Prozesse hilft xinetd (ehemals inetd). Dies ist ein Programm, das dabei Hilft auf einzelnen Ports eines Linux-Systems Dienste anzubieten. Man beschreibt seinen Dienst in einer config-Datei, wenn dann ein Verbindungsversuch auf dem angegebenen (und von xinetd angebotenen) Port stattfindet startet xinetd das angegebene Programm und leitet die Anfrage an dieses Programm weiter.
SMP Regeln
- verwende den Classic Server
- stelle die DefaultDbCachePages auf eine KLEINE Zahl (=75)
- Es funktioniert nur FirebirdCS-2.5.3.26780-0.i686.rpm, also die Classic 32 Bit Version.
- Nicht vergessen die firewall zu deaktivieren, oder zumindest Post 3050 öffnen
- firebird läuft noch über xinetd, also systemctl enable xinetd, systemctl start xinetd
joe /etc/xinet.d/firebird
# default: on # description: FirebirdSQL server # # Be careful when commenting out entries in this file. Active key entry should # be the first as some scripts (CSchangeRunUser.sh in particular) use sed # scripting to modify it. service gds_db { disable = no flags = REUSE socket_type = stream wait = no user = firebird bind = 192.168.115.224 server = /opt/firebird/bin/fb_inet_server }
OpenSuSE 42
zypper install firebird-classic systemctl enable firebird systemctl start firebird # # Sicherheitsrelevant! # # Ändere nun das SYSDBA Passwort von "masterkey" auf was ordentliches # /usr/lib64/firebird/utils/changeDBAPassword.sh
- Konfiguration /etc/firebird/firebird.conf
- Benutzerdatenbank /var/lib/firebird/
- SYSDBA Passwort ändern: changeDBApassword.sh
openSUSE 42.3
# # Installation # zypper addrepo http://download.opensuse.org/repositories/server:/database/openSUSE_Tumbleweed/server:database.repo zypper refresh zypper install firebird-server # # zukünftiger Autostart # systemctl enable firebird # # Start # systemctl start firebird # # Test # telnet localhost 3050
Windows 7/8/10/Server
- Ich rate von der Verwendung des Firebird- Servers unter Windows allgemein ab, es sollte immer wenn möglich ein Linux- Server verwendet werden. Wenn es nicht anders geht muss man - wie immer bei Windows - etwas schrauben dass es funktioniert
- Das Passwort ist nach der Installation immer masterkey
- In der Defender Firewall muss man die eingehenden Ports 3050 und 3051 öffnen
- Die "Firebird.conf" sollte so aussehen
# # Einstellungen für erfolgreiches Konnektieren von 2.5 Clients # AuthServer = Legacy_Auth AuthClient = Legacy_Auth UserManager = Legacy_UserManager AllowEncryptedSecurityDatabase = false WireCrypt = Enabled WireCompression = false RemoteAuxPort = 3051
Windows XP SP 2
Langsamer Applikationsstart seit Installation des Windows XP Service Pack 2
Voraussetzung: (Ursächlich ist das Service Pack 2 von Windows XP)
Problem:
Bis zu 10 Sekunden längerer Verbindungsaufbau bei Konnektierung auf den Linux Firebird Classic Server.
Lösung:
Die Firewall des Service-Pack 2 blockiert alle eingehenden Verbindungsversuche von aussen. xinetd versucht bei aktiviertem log_on_success = USERID den erfolgreichen Verbindungsaufbau zum firebird-dienst zu protokollieren. Dazu läuft ein Protokoll ab zur Verifizierung der Benutzer Identiät auf Port 113.
mehr Info auf http://grc.com/port_113.htm RFC auf http://www.faqs.org/rfcs/rfc1413.html
Dieser ist geblockt, xinetd gibt nach 3 maligem Versuch auf. log_on_success und log_on_fail sollte entfernt werden, oder auf HOST umgestellt werden:
joe /etc/xinetd.d/firebird // // Folgende beide Zeile so verändern oder ganz auskommentieren // log_on_success = HOST log_on_fail = HOST // ps -A | grep xinetd // merke Dir den PID des xinetd kill -SIGUSR2 <PID des xinetd> // // dadurch wird xinetd gezwungen seine konfiguration neu einzulesen. //
Alternative: öffnen des Port 113 auf den Windows XP Clients (von mir nicht empfohlen)
sollten Sie schon Windows XP Serivce Pack 2 erhalten haben, so deaktivieren Sie bitte die Anti-Virus Warnung:
Deaktivieren der Virenschutz-Warnmeldung
Start->Systemsteuerung->Sicherheitscenter->Empfehlungen->unteren Haken ankreuzen
es sollte sich folgendes Bild ergeben:
Firewall: aktiv. Automatische Updates: aktiv. Virenschutz: nicht überwacht.
OrgaMon wird geblockt: (wegen Webshop XML-RPC-Port)
siehe Installation.Arbeitsplatz
Firebird : Linux-Server
siehe Installation.Arbeitsplatz
Shell Befehle
netstat --numeric -p | grep fb_inet // anzeigen aller an firebird connectierten // (eigentlich fb_inet_server, jedoch wird der volle Name oft durch // netstat abgeschnitten) ps -A | grep fb // anzeigen aller firebird - Prozesse lsof <firebirddatenbankdatei> // anzeigen aller User auf einer firebird Datenbank lsof -p <PID eines fb_inet_servers> // anzeigen der Dateien, die der Prozess offen hat // es wird auch angegeben wer (welcher remote) connectiert ist.
/opt/interbase/bin/ibmgr -shut -user "SYSDBA" -password "masterkey" /opt/interbase/bin/ibmgr -start -forever
Verwendung als Embedded
- Dies bezeiht sich nur noch auf die freepascal win64 Programmierung
- die "fbclient.dll" der Version 3.0.7 ist automatisch eine embedded Version, einfach die .zip Distribution in das Anwendungsverzeichnis entpacken
- mit gbak kann man eine .fbak auf einem Netzwerk-share wieder in eine .fdb verwandeln, aber nur auf ein lokales Drive, also C:\ oder ein USB Stick F:\
- mit freepascal win64 ist mir das noch nicht gelungen, da ist noch ein problem
- man kann auf keine .fdb auf einem Netzwerk Share verbinden
- auch wenn man mit gfix die Datenbank in eine read-only Datenbank verwandelt hat
Verwendung mit http://drbd.org
Um mit Firebird eine gewisse Ausfallsicherheit zu erreichen können 2 Massnahmen getroffen werden.
Operation auf einer Partition / Blockdevice
normalerweise ist eine FirebirdSQL-Datenbank eine Datei, die mit wachsendem Inhalt der Datenbank immer grösser wird. Man kann aber einfach firebirdSQL anweisen eine ganze Partition für die Ablage der Datenbank zu verwenden. Die Datenbank-Grösse kann dann nur bis zur Partitions-Grösse anwachsen. Auf den Backup und Restore Prozess hat dies keinen Einfluss.
Eine Performance-Messung ergab praktisch identische Zugriffszeiten bei der Operation auf einer Partition im Vergelich zu einer Datei auf der selben Platte. Der Restore in die Partition hinein wurde mit 16 K Page Size durchgeführt.
Operation auf DRBD
DRkann eine Partition auf einen anderen REchner spiegeln. Host A wird zum Master, wenn ein Prozess auf Host A schreibend auf das Block-Device zugreift wird diese Änderung auf Host B per Netzwerk übertragen. Auch Host B ändert nun sein Abbild und beide Partitionen sind wieder gleich. Wir gewinnen einen gewissen Schutz beim Ausfall des Host A, dann können wir firebird auf Host B auf der Partition B starten.
Die Konfiguration
chkconfig --add drbd cat /proc/drbd
- resouce in /etc/drbd.conf auf beiden Systemen definieren
resource r0 { protocol A; meta-disk internal; device /dev/drbd1; on raib24 { disk /dev/sdb2; address 192.168.115.24:7789; } on raib30 { disk /dev/sdb1; address 192.168.115.30:7789; } syncer { rate 10M; } }
- Erstellen des /dev/drbd1
# # Ich hatte das Problem, dass die Partitionen leicht unterschiedlich gross waren. # Irgendwie hat die, in der Doku angesprochene "size determination method" versagt, # oder ich hatte die Aushandlungsphase versehentlich verhindert, da ich zunächst auf dem Primary # ohne Kopplung auf den Secondary die Metadata bereits geschrieben habe. # Hier sollte noch eine Step by Step anleitung kommen, die die VErbindung # VOR erzeugen der Metadaten setzt. Das wär' mir lieber! # Ansonsten könnte man sagen # Ich erstelle 2 PArtitionen, die einfach nur >=Size sind, danach setzte ich die Ursprünglich gedachte Size: # -d, --disk-size size # You can override DRBD's size determination method with this option. If you need to use the device before it was ever connected to its peer, use this option to pass the size of the DRBD device to the driver. Default unit is sectors (1s = 512 bytes). # If you use the size parameter in drbd.conf, we strongly recommend to add an explicit unit postfix. drbdadm and drbdsetup used to have mismatching default units.
drbdadm create-md all drbdadm -- --overwrite-data-of-peer primary all
# Ab hier kam ich in Probleme da ich beide Partitionen nicht genau gleicg gemacht hatte # Egal was ich eingetragen hatte, irgend eine Rundung verwarf mir meine Angaben # Es sind auch auf beiden Systemen nicht baugleiche Platten, so dass ich mir # dieses Problem mit der Unterschiedlichen Partitions-Geometrie erkläre # Es ging aber als ich die Sekundäre Partition etwas grösser machte, als die # bereits "metadata" initialisierte primäre Partition. Es scheint so dass dann # klaglos der Rest der Sekundären Partition unbenutzt bleibt. # @Secundary> drbdadm secundary all # Beim Restore einer DB mit gbak als root gab es kein Problem # aber der Zugriff auf die Partition war dann Firebird in der Rolle als Remote-Prozess nicht # möglich. Hier wird nämlich das Dateisystem (in dem Fall das Blockdevice System) in der Rolle des # User "firebird" angesprochen. Gute Infos zu dieser Thematik gibt es hier: # http://fghaas.wordpress.com/2007/06/04/using-drbd-directly-without-a-file-system/ # Versuch 1) ich habe die Rechte von /dev/drbd1 entsprechend angepasst! # @primary> chmod o+rw /dev/drbd1 # das ging genau 1mal, aber nach den "close" durch firebird waren die Rechte wieder auf # Original-Zustand zurückgesetzt. # Versuch 2) ich habe den owner von root auf "firebird" gesetzt, das ging wieder nicht lange gut # Versuch 3) ich wollte "firebird" zur Gruppe "disk" hinzufügen, das klingt eigentlich toll, # aber wie geht das? Über die ganzen Befehle kam ich nicht zu Ziel. # Ich habe einfach die Datei /etc/group editiert: # @primary> joe /etc/group # Bei "disk" muss hinten der User "firebird" angehängt werden # disk:x:6:firebird #
Usage with ZNS (a concept)
- a firebird database is stored to a single file, all the data, tables and indexes share the same file
- this concept is so clean, that you can even use a partition to store a database
- Data is organized by fixed size Pages, there are different Page-types - for Row-Data, Index-Tables, or Metadata
- firebird storage is optimized for typical blockdevice, open the file, read, append to the end, and update Pages
- a firebird file can only grow, but there are unused pages within a firebird file, the more the older is the file
why ZNS for NVMe
- NVMes are perfect Blockdevices for firebird? Yes, they seem to be, but internal they do a lot of work to keep expectations
- They only emulate a perfect Blockdevice by the Housholding Algos of their internal Controller Software
- Under the hood, there is dramatic action going on:
- Reading Data ist not the problem, just works like reading Bits from a RAM Chip
- Writing "new" Data to prior unused space is no Problem
- Updating, or overwriting data is a Problem, internally this is not possible
- Updating is done by erasing a Zone an writing it new from left to right
- Updating n-Bytes can result in writing n*2*y-Bytes
Give NVMe more Info
- If the OS would give more Information to the NVMe, Live for it could be much easier
- The NVMe could avoid internal housholding writes, this is prelonging livetime
- What Information is helpfull:
- What data belongs to a file
- When you start writing a file, please tell me its size (if known)
- What breaks the "blockdevice" game
- We must understand the "zone" Ecosystem
- We must arrange data in Zones
- forget random writes to files
- remember the "artefacts", let the nvme do the garbage collect (by "simple copy")
The new Firebird Storagemode
Pages
- Pages, from nowone can only be saved to the end of the file
- Page Number 0 is not nessesarly on position 0 of the file
- You must ask a "bitmap" layer to get the real position
Bitmap
- We must implement a new "translating" level for PageNumbers
- This persistent Datastructure maps Pagenumbers to the real world
- It grows from 0.. , but data is interpreted from EOF..0
type BitmapElement = record PageNumber: int64; Zone: int64; Seek: int64; StopLookingBack: boolean; end; Bitmap = array of BitmapElement;
- If you ask for a PageNumber you get a Zone and a Seek back
- If you get no answer, you can assume Zone=0 and Seek=PageNumber
- if StopLookingBack is true, do not trust older BitmapElements with this PageNumber
Page-Zones
- In my Picture i will only look at the "Write"- Aspect of an NVMe, reading is done by magic!
- Imagine a Data-Storage Room with hundreds of Tape-Recorders
- One Tape is one Zone, the storage Controller can
- erase an entire single tape by sending the command resulting in a "magnetic flash"
- write data from 0..EOF the Tape, no update, no overwrite, only appending data until the tape is at its end
- firebird should ask how big the Zone-Size is and use now Zones for writing the Pages of all kind
- If a Page must be updated, do not write to the original file position of the page (no, dont use seek+write), append it to the actual End of the Database-file, this is in the highest
- So we have an Old representation and a new in our Page-File - wich is the correct one?
Bitmap-Zones
- With the help of a Bitmap-Datastructure firebird can calculate the true Position of Pages
- With a "perfect" ordered Database-File the Bitmap is empty
- If new or recently updated Pages grow the file the Bitmap grows.
- firebird has to calculate PageNo+Bitmap -> ZoneNumber, SeekPosition
- Even the Bitmap can only grow, there is no "updated" Bitmap-Data
- A persistent Bitmap must be read from right to the left (from newly saved Data to older ones)
- A newer Information about a Page-Position makes all the old-Data about Pages obsolet
simple copy
- use NVMe "simple copy" to "garbage collect" bitmap and Page File
The Page-Storage
DDXXDXDDDDDXXXXX
- D=actual real Page
- X=artefact of an old now unused page
- By reading old Parts of the Bitmap, firebird knows where artefacts live
- with the NVMe simple copy command you can ...
- move all the "D" to the append position
- send the info that the hole zone is now free!
- after such a "simple copy" the bitmap must mark the X Position as censored, that means a reserach and use of Position Data in old Bitmap Data is forbidden
The Bitmap-Storage
XXXBXBBBBBBXBBBBB
- if you parse the entire Bitmap from rigth to left, before reaching "0", there is a Point P where you have all the information you need for the hole Picture
- this is because some Information is "censored" and so, has no Information Content any more
- so you can free 0..P, in our sample you can free XXX
this causes more corruption?
- appending a new Pages? No risk
- updating a page means
- A: appending the page to the higest Page-Zone
- B: appending Bitmap-Info about this page writing a Page to the and add this Information to the Bitmap
- C (optional):a Page-Zones gets free, because the updated page was the last living object on that zone
- D (optional):a Bitmap-Zone gets free, because a zone is complete censored know (by Step C)
-> if you ensure A+B+C+D inside an atomic transaction, if a file system can help, this is save
Verwendung mit PHP
Die Verwendung unter PHP ist möglich indem man die Extension "interbase" bereitstellt.
64-bit
Bekomme ich bei mir nicht zum laufen. Nach der Compilierung eines Mini-Programmes zur Abprüfung der existenz von libfbclient kann das Programm die Bibliothek nicht laden: "not compatible version of" ...
- Traurig: Nach so vielen Jahren 64-Bit läuft das immer noch nicht!
32-bit
- Vorbereitung
zypper install libxml2-devel zypper install FirebirdCS-2.5.0.26054-ReleaseCandidate3.i686.rpm
- Ermittle die PHP Versionsnummer, damit du weist welchen Source-Tar-Ball du ziehen must
php -v
- Lade vom Museum die Source-Code Distribution des PHP, in diesem Beispiel hat die Versionsprüfung 5.1.0 ergeben
wget http://museum.php.net/php5/php-5.1.0.tar.gz gzip -d php-5.1.0.tar.gz tar -xf php-5.1.0.tar cd php-5.1.0
- Compiliere Dir selbst die Extension "interbase.so", ermittle zuvor den Installationspfad von firebirdsql, ab 2.5 heisst er z.B. nicht mehr "/opt/firebird" wie hier angegeben
./configure --with-interbase=shared,/opt/firebird make
- so, jetzt das Compilat noch PHP zur Verfügung stellen
cp modules/interbase.so /usr/lib/php5/extensions
- Nun reicht es, im Verzeichnis
/etc/php5/conf.d
die Dateiinterbase.ini
anzulegen:
extension=interbase.so [Interbase] ibase.timestampformat=%m-%d-%Y %H:%M:%S
den Apache 2 neu starten
rcapache2 restart
Diagnose, ob jetzt das interbase Module geladen ist:
php --modules
auf Fehler in der folgenden Datei achten:
/var/log/apache2/error_log
Win32
Damit PHP auf Interbase/Firebird Datenbanken zugreifen kann, müssen die Routinen, die das ermöglichen, beim Start von PHP als Erweiterung geladen werden. Dies geschieht mit Hilfe zweier Einträge in der "php.ini". Erstens muss der Eintrag "extension_dir= " auf das Verzeichnis mit den Extension-Dlls gesetzt werden. Diese befinden sich standardmäßig im Verzeichnis "extensions". Falls PHP zum Beispiel in "C:\Programme\Php" installiert wurde, liegen die Erweiterungs-Dlls im Verzeichnis "C:\Programme\Php\extensions". Der Eintrag in der "php.ini" lautet dann:
Win32 extension_dir = "C:\Programme\Php\ext" Linux extension_dir = "/usr/lib/php/extension"
Zweitens gibt es in der "php.ini" einen Abschnitt, der sich "Dynamic Extensions" nennt. Dort sind alle Erweiterungen in der Form ";extension=php_....dll" aufgeführt. Da ein Semikolon am Anfang steht, beachtet PHP diese Zeile nicht als Eintrag sondern als Kommentar. In der Zeile ";extension=php_interbase.dll" muss dieses Semikolon nun entfernt werden.
Win32 extension=php_interbase.dll extension=php_gd2.dll Linux extension=interbase.so
Der WebShop erfordert, dass Timestamps im richtigen Format übernommen werden. Dies geschieht durch folgende zwei Zeilen, die am besten ans Ende der "php.ini" gestellt werden:
[Interbase] ibase.timestampformat=%m-%d-%Y %H:%M:%S
Jetzt sollten die PHP-Routinen für die Interbase-Anbindung zur Verfügung stehen. Falls dies nicht so ist, liegt es vielleicht daran, das die "php.ini" im falschen Verzeichnis liegt (siehe Ende vorletztes Kapitel) oder der Pfad im Eintrag "extension_dir=" falsch gesetzt ist.
Achtung: Nach einer Änderung muss der Apache-Webserver mit "Startmenü\Alle Programme\Apache HTTP Server\Control Apache Server\Restart" neu gestartet werden.
Datensicherung
Unter Linux setzt firebird die Dateizugriffsrechte bei der erstellung der Datenbank-Datei auf
-rw-rw--- firebird firebird
das ist eher unpassend, da ich mit rsync die Dateien nun nicht lesen also auch nicht sichern kann. Die Maske müsste eher
chmod 664 sicherung_00000006.fdb
"664" lauten. Bisher hab ich noch nicht rausgefunden wie und wo man das ändern kann. Hat man alle firebird Datenbanken in einem Unterverzeichnis vereint, so kann man mit einem Befehl alle *.fdb Dateien korrekt anpassen.
cd /your-firebirdsql-database-root-path chmod 664 `find -name *.fdb`
Parallele Dienstverarbeitung
Fragestellung: Im Mehrbenutzerbetrieb fallen Aufgabenstellungen an (Jobs). Wie kann man mehrere Arbeiter-Prozesse einsetzen, und deren Arbeit über eine Datenbank koordinieren? Insbesondere ist zu vermeiden, dass sich 2 Arbeiter den gleichen Job holen und abarbeiten.
Beispiele: eMail Versenden, oder an einem ARTIKEL-Datensatz eine Datenzelle Updaten!
Dazu muss eine Abfrage das Arbeitsvolumen ausgeben können, dieses wird pollend ausgeführt. Es sollten schon die "in Arbeit befindlichen" ausgeklammert werden. Entscheidet sich ein Arbeiter für einen Datensatz muss er diesen Datensatz für sich verlässlich exclusiv reservieren können, dabei wird sein eigener eindeutiger ~Kontext~ (in ARBEITER) und das Reservierungsdatum (in ZUGETEILT) eingetragen. Für jede Arbeit wird ein Verfallsdatum angegeben an der diese Reservierung wieder verfällt, die Aufhebung von Reservierungen macht ein globaler Arbeiter.
Nach dem ERFOLGREICHEN setzen des exclusiven (atomaren) Abstecken des Claim kann die Arbeit beginnen. Um den Streit (der immer eindeutig entschieden werden muss) zwischen den Arbeitern zu vermeinden soll jedem Arbeiter eine "Prämisse" mitgegeben werden, z. B. von "oben nach unten", oder "immer das Mittlere Element", oder von "unten nach oben" oder "RID DIV 5 = 3" usw. Ziel wäre es dass nicht unbedingt im an den aktuellen Anforderungen gearbeitet wird, sondern immer auch an ganz alten.
Ist die Arbeit erledigt so wird ein gewisser "Erledigt"-Status verbucht, der Datensatz ist dadurch nicht mehr "offen", so dass die "offene"-Selektion diesen Datensatz nicht mehr sieht. Auch für die verlorengegangenen Arbeiter ist dies dann unsichtbar.
Lösung
Von einem einzelnen Arbeiter-Thread werden immer folgende Arbeiten ausgeführt
- Gibt es "offene" Sätze mit "ARBEITER=~Kontext~" -> arbeite diese ab bis leer
select RID from TICKET where (ART = 22) and (ARBEITER='V97XWY2Q6') and (BEENDET is null) # # Ergibt sich hier ein Ergebnis wird dieser Job abgearbeitet #
- Ist die Arbeitsliste fertig: Gewisse Anzahl von Arbeiten für mich reservieren (atomar, multithread fest!)
update TICKET set ARBEITER = 'V97XWY2Q6', ZUGETEILT = CURRENT_TIMESTAMP where RID= ( select first 1 RID from TICKET where (ART = 22) and (ARBEITER is NULL) )
- Von einem Service-Thread werden ab und an folgende Arbeiten ausgeführt
- Arbeiter-Punzen (in diesem Fall ARBEITER='V97XWY2Q6') deren Zuteilung zu lange her ist, und die noch nicht BEENDET sind: Feld ARBEITER leeren. Dadurch werden diese Jobs frisch zugeteilt.
- Vollständig erledigte Vorgänge die weit zurückliegen löschen
GHOST - Attachements
Ich habe offene Verbindungen beobachtet (in MON$ATTACHEMENTS), die auch Transaktionen offen halten, und ich denke dadurch werden zahlreiche Record-Versions generiert. Dem Rechner wurde sogar inzwischen eine neue IP-Adresse zugewiesen und die Verbindung war immer noch offen. Problemlos war jedoch die Löschung der entsprechenden zeile in MON$ATTACHEMENT!
Ein Sweep blockiert dann die ARTIKEL Tabelle. Der Sweep ist sehr langsam.
Entwicklung dieses Fehlers
27.01.2012
heute hatten wir wieder die Störung der Art, dass ein Zugriff auf die ARTIKEL Tabelle langsam bzw. "ewig" dauert. Leider war diesmal kein schneller backup / restore Lauf mit der aktuellen Datenbank möglich. Wir hatten somit einen Blackout von gestern 15:03 bis 13:00 Uhr.
Ich habe etwas geforscht und nun herausgefunden, woran es NICHT liegt:
- der Webshop hält in diesem Moment keine Verbindung offen
- es besteht in diesem Moment keine offene Transaktion die alles andere blockiert
- es liegt nicht an einer einzelnen Verbindung, so dass man nach Trennung dieser Verbindung sagen kann die Störung sei behoben
- von der Festplatte kam keine Störungsignal, auch das Dateisystem ist OK
Ergebnis: Zugriff auf die ARTIKEL Tabelle ist möglich aber sehr sehr langsam, irgendein Problem scheint es hier zu geben. Ich ziehe den Datenbank Server auf Paris um, mit der firebird Version 2.1.4.
-> Nun meine Frage: Wer hat eine Idee / eine Vermutung was ursächlich sein könnte: Also war zwischen 11:20 und 12:00 Uhr irgend etwas ungewöhnlich? Jede Idee ist willkommen!
Hallo zusammen,
also die Datenbank läuft nun auf Paris (der Rechner in der Garage). Sie wird jede Stunde gesichert. Leider konnte ich meinen Plan nicht 100% durchsetzen: Anstelle der 2.1.4 Version MUSS ich 2.5.2 einsetzen, da es keine Weg zurück gibt. Mit Geldud und Spucke habe ich unsere "Crash" Datenbank doch noch sichern können: Das bedeutet wir verfügen auf Anfrage über einen Funktionierenden Spare, d.h. auch die ARTIKEL Tabelle ist beim Spare funktionsfähig - ich denke die Warenbewegungen müssen im Spare auch geprüft werden und in der aktuelle Datenbank nachgezogen werden ...
-> bis Montag!
07.02.2012
Hallo zusammen,
heute nacht ist beim geplanten Backup- Restore- Lauf das ARTIKEL-Problem aufgetreten. Wie beim letzten Mal funktionierte das Backup jedoch, aber nur gaaanz langsam. Wir haben keinen Datenverlust aber waren 23:00 - bis 2 Uhr offline. Wir wissen jetzt also dass "newyork" als Server in Ordnung ist. Das Problem tritt somit bei 2.5.1 und beim Snapshot (kommende 2.5.2 Version) auf und wurde also bisher nicht gelöst. Die Haltbarkeit einer Datenbank ist also im Moment so ca. 10 Tage, wir machen als Massnahme immer Montags einen Backup- Restore- Lauf. Ich versuche das zu automatisieren:
Webshop ausschalten. Alle OrgaMons rausschmeissen BAckup- Restore- newyork: xmlrpc starten Wien Starten London starten Webshop einschalten.
Hallo zusammen,
wie der Betreff schon ankündigt bin ich mir noch nicht 100% sicher. Es liegt am Transaktionsmodell des firebird Servers, in Verbindung mit einem "sweep" VErhalten das ich im Moment als Bug in firebird einstufe. Also die Ursache ist:
Ein von ARTIKEL abhängige Transaktion T1 startet, wird aber nicht beendet. In meinem Fall war dies *NICHT* der Shop sondern eine Arbeitsstation. Der Tagesabschluss hämmert auf ARTIKEL ein, Grund "Rang" Berechnung UND Lieferzeitberechung. Da T1 noch in der Luft hängt baut firebird eine künstliche Welt auf die für T1 so aussieht wie zum Startzeitpunkt von T1. Das resultiert in 180.000 "alten" Versionen der Records in ARTIKEL. Und das pro Tagesabschluss! Läuft nun dieser OrgaMom mehrere Tage *UND* wird dann beendet, wird es richtig Stressig für firebird: Alle Record-Versionen werden jetzt aufgeräumt -> Die Tabelle ARTIKEL hängt. Warum das aufräumen einerseits alle anderen Blockiert, andererseits mit 1% CPU Last durchgeführt wird ist für mich en Rätsel ...
-> ich leite Schritt für Schritt Massnahmen ein ...
15.02.2012
Ich habe heute ein Geister-Attachement gekillt (2 offene Transaktionen), dann sichergestellt dass alle OrgaMons frisch gestartet sind. Danach habe ich einen Sweep ausgeführt. Während des Sweeps (ca. 15 min) habe ich parallel immer mal wieder die Record-Versions geprüft. Die gingen im Verlauf "schnell" runter auf fast 0!
newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.50, total versions: 313751, max versions: 25 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.50, total versions: 313751, max versions: 25 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.50, total versions: 313751, max versions: 25 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.41, total versions: 200754, max versions: 22 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.41, total versions: 195344, max versions: 22 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.41, total versions: 190157, max versions: 22 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.42, total versions: 153594, max versions: 22 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.77, total versions: 48805, max versions: 21 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.84, total versions: 38239, max versions: 21 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 11.97, total versions: 26478, max versions: 21 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 12.00, total versions: 19429, max versions: 21 newyork:~ # /opt/firebird/bin/gstat -r -t ARTIKEL prod.fdb | grep versions Average version length: 15.33, total versions: 6, max versions: 2
Bleibt zu klären, wer oder was offene Transaktionen hält!
16.02.2012
Ich versuche über das Produkt FB Trace-Manager von Thomas Steinmaurer zu ergründen wo offene Transaktion verbleiben. Ich hab' einige Zeit gebraucht zuerst mal zu verstehen was der Trace Manager überhaupt ist. Hier mal eine grundsätzliche Info:
- ab firebird 2.5 kann ein Client über das Netzwerk zum firebird Datenbank-Server ein Text-Verbindung öffnen und sich Infos aus verschiedenen Bereichen wünschen. Also man wünscht sich Infos wenn eine neue Verbindung zustande kommt, oder wenn eine Transaktion gestartet oder beendet wird. Tritt auf dem Server dieses Ereignis ein, sendet er einen entsprechenden Text an den Client. Das Trace API ist also so eine Art remote logging Mechanismus, in den man sich einklinken kann, den man steuern kann. Das Trace-Interface ist Multi-User fähig!
- Der FB-Trace-Manager bereitet den Roh-Text ordentlich auf und stellt ihn tabelarisch dar. Unnötige Infos lassen sich rausfiltern. Ob der Trace-Manager ein Tracking bestizt weis ich noch nicht ...
17.02.2012
i did not find the guilty left open statement by now, but we nearly can reproduce the error by now! We let OrgaMon be active after some work with it, after 24 h we had again 330.000 "versions" in the ARTIKEL Table (gstat -r). Then - I just closed this OrgaMon, firebird started clean up immediatly down to 14 versions! This took 12 Minutes.
At Monday we make the next test: I have now a Button in OrgaMon "commit W Transaction", where the User can do a "IBO.Transaction_W.CommitRetaining" manually to my gultiy W-Transaction, i give you feedback what happened ... (we have the situation under control! It is not any more in an emergency state yet! Thanks yery much for your help!)
20.02.2012
- it is all clear now: On Form Opens a IB_Query because a Grid is linked. This form *never* makes a change. It it just like "select * from ARTIKEL", this is done inside my default transaction (the W-Transaktion!) This OrgaMon is now left open for a long time ...
- Another OrgaMon makes "Tagesabschluss" and update ARTIKEL in the sense of "update ARTIKEL set LIEFERZEIT=null". This generates a lot of record versions because the long running orgamon did not make a commit ...
29.02.2012
Until Jason has a "silent commit and reopen on demand"- fix ready: Here is my workaround. it is a automatic cut-connection script wich is executed by OrgaMon automatically at noon.
- OLAP Skript: "System.Tagwache.Verbindungen_trennen.OLAP.txt"
-- -- Skript zum Anzeigen / Beenden all zu langer Datenbankverbindungen -- $SERVERS=('192.168.100.90','192.168.100.91','192.168.100.182') $STUNDEN=8 select MON$$ATTACHMENT_ID, MON$$TIMESTAMP, MON$$REMOTE_ADDRESS from MON$$ATTACHMENTS where (MON$$STATE=1) and ((CURRENT_TIMESTAMP - MON$$TIMESTAMP) > ($STUNDEN.0 / 24.0) ) and (MON$$REMOTE_ADDRESS not in $SERVERS) save numeric MON$ATTACHMENT_ID - excel save as html - nop - repeat delete from MON$$ATTACHMENTS where (MON$$ATTACHMENT_ID=$RID) -
28.01.2014
will den Fehler mal reproduzieren. recht aktueller Linux-Server 2.5.2 wird bereits genutzt.
- OrgaMon öffen
- die delikate Aktion im Tagesabschluss
- prüfung mit Anzeige der Record-Versions
- OrgaMon schliessen
- prüfung der langsamen Abnahme der Record-Versions
firebird 3.0
- Für die Zukunft ist ungewiss ob die Quellen des OrgaMon auf nativ Firebird 3.0 umgestellt werden
- Es steht immer noch im Raum ev. auf Postgresql umzustellen
- Als Zwischenlösung konnektiere ich erfolgreich mit dem OrgaMon in Verbindung mit einer firebird Client DLL 2.5.x auf einen Firebird 3.0 Server
SYSDBA Passwort abändern
gsec -user SYSDBA -password masterkey -modify sysdba -pw MyKey37
Firebird Datenbank Crash?
konkrete Verwendung einzelner Befehle für backup und restore. siehe ibreorg.bat in der Anlage. (der ist leider für 32-DOS-Box!) die Befehle müssen auch unter linux so gehen. der Pfad ist aber /opt/interbase/bin/gbak .... --- snip @echo off REM ------------------------------------------------- REM Reparatur einer inkonsistenten FireBird Datenbank REM REM (c) Andreas Filsinger, www.orgamon.org REM ------------------------------------------------- REM REM Usage REM REM reorg <Pfad und Name der Datenbank OHNE ".gdb"> REM REM -------------------------------------------- REM REM ACHTUNG: richtigen Pfad ermitteln, indem Sie nach der REM Datei gbak.exe suchen lassen. Und hier eintragen: REM SET IBBIN=D:\programme\borland\interbase\bin\ REM REM -------------------------------------------- REM 1) fix erros REM %IBBIN%gfix -mend -full -ignore -user "SYSDBA" -password "masterkey" %1.fdb REM -------------------------------------------- REM 2) backup fixed base REM %IBBIN%gbak -backup -v -ignore -garbage -user "SYSDBA" -password "masterkey" %1.fdb %1_neu.fbak REM -------------------------------------------- REM 3) restore base REM REM zusätzlich noch "-i" wenn Indizes deaktiviert werden sollen REM %IBBIN%gbak -r -v -p 16384 -user "SYSDBA" -password "masterkey" %1_neu.fbak %1_neu.fdb REM -------------------------------------------- REM 4) check new one REM %IBBIN%gfix -v -f -user "SYSDBA" -password "masterkey" %1_neu.fdb REM -------------------------------------------- --- snap
Bemerkungen ===========
a) Backup-möglich aber fail beim Restore: wegen inkonsistenter Indizes ich habe mal erlebt, das foreign Key nicht mehr konsistent waren, und deshalb der restore abgebrochen hat. Alle Indizes kann man jedoch als inaktiv restoren, (Option -i ) nach löschen /clearen der "Schuldigen" kann man alle indizes wieder aktivieren, wieder ein backup, wieder ein restore -> alles wieder gut. damit der OrgaMon alle indizes sehen kann braucht er "out.txt". Das ist die Ausgabe eines erfolgreichen restores, der alle indizes enthält. Unter linux gibt man die Ausgabe von gbak mit 2>/freigabe/out.txt in eine Datei aus.
firebird-Erkenntnis ===================
internal gds software consistency check (partner index description not found (175))
dieser Fehler tritt beim löschen eines Datensatzes auf, der eventuell durch einen foreign key einer anderen Tabelle referenziert werden könnte. Ist dieser key deaktiviert so kann keine Aussage getroffen werden, ob das löschen ok ist, dieser interne Fehler ist die Folge!!
Page Type Error
Behebung des Fehlers "Wrong page type":
Backup ist nicht mehr möglich
Beobachtung: tokio:/srv/smb/fdb # gbak -b -g -ig -user sysdba -password **** /srv/smb/fdb/k-prod.fdb k-prod.fbak gbak: ERROR:database file appears corrupt (/srv/smb/fdb/k-prod.fdb) gbak: ERROR: wrong page type gbak: ERROR: page 136509 is of wrong type (expected 4, found 5) gbak: ERROR:gds_$compile_request failed gbak:Exiting before completion due to errors Auch mit der Option -mend : kein Erfolg
GFix ist nicht mehr möglich
Beobachtung: tokio:/srv/smb/fdb # gfix -v -f -user sysdba -password * /srv/smb/fdb/k-prod.fdb Summary of validation errors Number of pointer page errors : 1 Number of database page errors : 28
IBAid "Repair" hat keine Wirkung
- der Direct Fix läuft durch und erweckt den Eindruck dass er das Problem gelöst hätte
- After the "fix", i did the suggested final steps: There were the known, old errors, finally gbak fails!
server:/srv/firebird/prod # gfix -v -full -user sysdba -password **** /srv/firebird/prod/k-prod.fdb Summary of validation errors Number of pointer page errors : 1 Number of database page errors : 28
server:/srv/firebird/prod # gfix -mend -ig -user sysdba -password **** /srv/firebird/prod/k-prod.fdb Summary of validation errors Number of pointer page errors : 1 Number of database page errors : 28
server:/srv/firebird/prod # gbak -b -g -ig -user sysdba -password **** /srv/firebird/prod/k-prod.fdb k-prod.fbak gbak: ERROR:database file appears corrupt (/srv/firebird/prod/k-prod.fdb) gbak: ERROR: wrong page type gbak: ERROR: page 136509 is of wrong type (expected 4, found 5) gbak: ERROR:gds_$compile_request failed gbak:Exiting before completion due to errors
IBAid "Exract" bringt die Lösung
1) Beende alle Datenbank-Dienste und stelle die fdb bereit 2) Erstelle aus dieser defekten fdb eine leere fdb gleicher Metadatenstruktur gbak -b -m -user sysdba -password ***** /srv/firebird/prod/2/l-prod.fdb l-prod.fbak gbak -v -r -p 16384 -user sysdba -password ****** l-prod.fbak empty-prod.fdb 3) Starte IBAid und gehe direkt über den Wizzard "Extract" <Next> danach im Wesentlichen die Standard-Optionen lege die empty-.fdb auf deinen firebird server und geben die Connect Daten an 4) Es folgt dann das befüllen der fdb durch IBAid dieser Vorgang hat in meinem Fall 7 Stunden gedauert
Backup / Restore
#!/bin/sh # # parameter customize # NAMESPACE=yourname DBPWD=******** # # JJJJ-MM-DD # BAND=$(date +%Y-%m-%d) # # backup # rm $NAMESPACE-$BAND.fbak /opt/firebird/bin/gbak -V -B -USER SYSDBA -PASSWORD $DBPWD $NAMESPACE.fdb $NAMESPACE-$BAND.fbak # # restore # rm $NAMESPACE-$BAND.fdb /opt/firebird/bin/gbak -V -R -P 16384 -USER SYSDBA -PASSWORD $DBPWD $NAMESPACE-$BAND.fbak $NAMESPACE-$BAND.fdb chown firebird $NAMESPACE-$BAND.fdb chgrp firebird $NAMESPACE-$BAND.fdb # # clean-up # rm $NAMESPACE-$BAND.fbak # # #
Charset
- der Charset ist im Moment noch "NONE", ist implizit aber eigentlich "ISO8859_1"
update RDB$$DATABASE set RDB$$CHARACTER_SET_NAME='ISO8859_1'
FileCreate 660
- fdb Dateien werden mit den Recht 660 angelegt, manchmal kann ein Client die Datenbank-Datei dann nicht löschen
- auf dem Server, der das Share /srv/firebird freigibt
# # "nobody" wird in die Gruppe "firebird" verbracht # usermod -a -G firebird nobody
Prüfen
joe /etc/group # # Es muss eine Zeile geben # firebird:x:495:nobody
UTF8-Migration
create database 'orgamon.fdb' default character set UTF8 collation de_de; create table PERSON ( RID int64 not null primary key, last_name varchar (50), first_name varchar (50));