Bücher

Wie man das Koha „auto increment“ Problem lösen kann

Wir verwenden Koha für unsere Bibliothek, eine sehr mächtige und tolle Open Source Software. Auf Mailingliste des Projekts hatte ich bereits vom „Koha auto increment“ – Problem gelesen und hoffte, dass es uns nicht betraf. Doch vor einigen Wochen kam einer unserer Mitarbeiter der Schulbibliothek zu mir und gab mir ein Buch, dass sich nicht zurückgeben ließ. Jedes mal, wenn man versuchte, das besagte Buch zurückzugeben, bekam man folgende Fehlermeldung:

Koha auto increment error

Unter Mehr → Über Koha im Reiter „Systeminformationen“ konnte ich dann sehen, dass einige Bücher von diesem Problem betroffen waren.

Koha Systeminformationen

Doch worin liegt eigentlich das Problem? Wie konnte es dazu kommen?

Das Problem

Im Koha Wiki gibt es zu diesem Datenbankproblem eine eigene Wiki-Seite. Koha verschiebt Einträge zwischen Datenbanktabellen, wenn man z.B. einen Benutzer oder ein Buch löscht. Das gleiche passiert mit Ausleihen. Die Einträge in diesen Tabellen haben eine eindeutige ID, welche normalerweise automatisch hochgezählt wird (auto increment). Das Problem ist allerdings, dass MySQL diese Zähler nur im Arbeitsspeicher speichert und nicht auf der Festplatte. Dies tritt nur auf, wenn Einträge gelöscht werden. Ein Beispiel:

  • Ich erstelle einen neuen bibliographischen Eintrag (z.B. ein Buch). Es wird u.a. in der Tabelle biblio gespeichert. Der Eintrag bekommt die ID 1. Der nächste Wert für die ID müsste also 2 sein.
  • Jetzt lösche ich dieses Buch wieder. Der Eintrag wird in die Tabelle deletedbiblio verschoben. In der Tabelle biblio gibt es jetzt keinen Eintrag mehr.
  • Ich starte den MySQL-Server neu. Dadurch wird der interne Zähler für die IDs zurückgesetzt.
  • Nun lege ich ein neues Buch an. Es bekommt nicht die ID 2, sondern 1, weil es ja keinen Eintrag mehr in der Tabelle biblio gibt.
  • Wenn ich jetzt dieses Buch lösche, wird es zwar aus der Tabelle gelöscht, aber nicht in die Tabelle deletedbiblio verschoben, da es dort schon einen Eintrag mit dieser ID gibt. Die Folge ist, dass in diesem Fall mein Eintrag für immer verloren ist.

Das passiert wie gesagt nicht nur mit bibliographischen Einträgen, sondern auch mit Ausleihen, Benutzern etc. Aus diesem Grund warnt Koha in den aktuellen Versionen vor dem Problem. Damit ist es aber noch nicht behoben.

Das Koha „auto increment“ Problem reparieren

Um zukünftig einen Datenverlust zu vermeiden, bringen wir MySQL bei, die IDs nicht zurückzusetzen, v.a. nicht auf einen Wert, den wir schon einmal verwendet haben. Dazu öffnen wir die Datei /etc/mysql/my.cnf oder /etc/mysql/mariadb.conf.d/50-server.cnf (wir verwenden einen Ubuntu 16.04 LXD Container mit MariaDB) und ergänzen im Abschnitt [mysqld] folgende Zeile:

init-file=/var/lib/mysql/init-file_koha.sql

Dann erstellen wir eben diese Datei mit

$ sudo nano /var/lib/mysql/init-file_koha.sql

und kopieren den folgenden Inhalt in die Datei:

USE koha_DB_Name;
 
SET @new_AI_borrowers = ( SELECT GREATEST( IFNULL( ( SELECT MAX(borrowernumber) FROM borrowers ), 0 ), IFNULL( ( SELECT MAX(borrowernumber) FROM deletedborrowers ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE borrowers AUTO_INCREMENT = ', @new_AI_borrowers );
PREPARE st FROM @sql;
EXECUTE st;
 
SET @new_AI_biblio = ( SELECT GREATEST( IFNULL( ( SELECT MAX(biblionumber) FROM biblio ), 0 ), IFNULL( ( SELECT MAX(biblionumber) FROM deletedbiblio ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE biblio AUTO_INCREMENT = ', @new_AI_biblio );
PREPARE st FROM @sql;
EXECUTE st;
 
SET @new_AI_biblioitems = ( SELECT GREATEST( IFNULL( ( SELECT MAX(biblioitemnumber) FROM biblioitems ), 0 ), IFNULL( ( SELECT MAX(biblioitemnumber) FROM deletedbiblioitems ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE biblioitems AUTO_INCREMENT = ', @new_AI_biblioitems );
PREPARE st FROM @sql;
EXECUTE st;
 
SET @new_AI_items = ( SELECT GREATEST( IFNULL( ( SELECT MAX(itemnumber) FROM items ), 0 ), IFNULL( ( SELECT MAX(itemnumber) FROM deleteditems ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE items AUTO_INCREMENT = ', @new_AI_items );
PREPARE st FROM @sql;
EXECUTE st;
 
SET @new_AI_issues = ( SELECT GREATEST( IFNULL( ( SELECT MAX(issue_id) FROM issues ), 0 ), IFNULL( ( SELECT MAX(issue_id) FROM old_issues ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE issues AUTO_INCREMENT = ', @new_AI_issues );
PREPARE st FROM @sql;
EXECUTE st;
 
SET @new_AI_reserves = ( SELECT GREATEST( IFNULL( ( SELECT MAX(reserve_id) FROM reserves ), 0 ), IFNULL( ( SELECT MAX(reserve_id) FROM old_reserves ), 0 ) ) + 1 );
SET @sql = CONCAT( 'ALTER TABLE reserves AUTO_INCREMENT = ', @new_AI_reserves );
PREPARE st FROM @sql;
EXECUTE st;

Wichtig: In der ersten Zeile müssen wir unbedingt koha_DB_Name mit dem Datenbanknamen unserer Koha-Installation ersetzen. In der Regel ist das koha_name_der_koha_instanz, also z.B. koha_library.

Zum Schluss starten wir noch MySQL bzw. MariaDB neu:

$ sudo service mysql restart

Fehlerhafte Datensätze aufräumen

Nun haben wir zwar verhindert, dass das Problem wieder auftritt, aber es sind immer noch unserer alten Datensätze vorhanden. Ein Weg ist, die entsprechenden Einträge aus den deleted* Tabellen zu löschen. Damit verliert man vielleicht ein paar statistische Informationen, aber auf die können wir in unserer kleinen Schulbibliothek verzichten. Sonst haben wir bisher keine negativen Auswirkungen feststellen können.

Um die „fehlerhaften“ Datensätze zu löschen, müssen wir uns zuerst an unserem Koha-Server anmelden. Dann loggen wir uns in die MySQL-Konsole ein mit

$ sudo mysql -p koha_datenbankname
Enter password: 
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 115
Server version: MariaDB Ubuntu 16.04

Copyright (c) 2000, 2017, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [koha_datenbankname]>

Oben im Screenshot sieht man, dass unsere fehlerhaften Datensätzen in den Tabellen biblio und deletedbiblio sind. Die IDs sind doppelt und wir löschen die IDs aus einer der beiden Tabellen, konkret aus deletedbiblio. Wir überprüfen zuerst, welche Datensätze betroffen sind:

MariaDB [koha_datenbankname]> SELECT * FROM deletedbiblio WHERE biblionumber IN (*hier die IDs aus dem Webinterface kopieren*);

Wenn wir die Datensätze wirklich löschen wollen ändern wir den Befehl leicht ab:

MariaDB [koha_datenbankname]> DELETE FROM deletedbiblio WHERE biblionumber IN (*hier die IDs aus dem Webinterface kopieren*);

Falls es z.B. auch problematische Datensätze mit den Ausleihen gibt, würde der Befehl so lauten:

MariaDB [koha_datenbankname]> DELETE FROM old_issues WHERE issue_id IN (*hier die IDs aus dem Webinterface kopieren);

Nun zeigt Koha keine fehlerhaften Datensätze mehr an:

Koha Info

Fazit

Wenn man dieses Problem in seiner Koha-Installation hat, ist es sehr ratsam dieses Problem zu lösen. Allerdings gibt es verschiedene Ansätze. Der oben beschriebene Weg ist ein schneller Fix, der aber unter Umständen nicht für jede Installation in Frage kommt. Seitens Koha wird noch an einem Skript gearbeitet, dass das Problem später automatisch beheben soll. Trotz diesem Datenbankproblem haben wir den Umstieg auf Koha bisher nicht bereut. Es ist und bleibt eine tolle Software, die sicher ihre Einarbeitungszeit braucht, aber der Gewinn, die Flexibilität und die damit gewonnen Freiheiten sind scheinbar grenzenlos.

Setzt du Koha ein? Welche Erfahrungen hast du bisher gemacht?

3 Comments:

  1. Was zum Teufel, was ist das denn für ein Datenbankdesign oO

    Die ganze extra Tabelle für den deleted Kram ist doch völliger Schwachsinn. Warum macht man nicht einfach ein tinyint/bool oder datetime „deleted“ in der eigentlichen Tabelle?

  2. zefanja

    @Tobias: Die Entwickler von Koha haben sicher ihre Gründe dafür, vielleicht würde man es heutzutage auch anders machen und die Struktur ist historisch bedingt.

Leave a Reply:

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert