webentwicklung-frage-antwort-db.com.de

CREATE FUNCTION-Fehler "Diese Funktion hat keine DETERMINISTIC-, NO SQL- oder READS SQL-DATEN"

Unsere Datenbank hat eine Funktion zum Generieren einer Bestellnummer. Es liest einen Wert aus einer Einstellungstabelle, erhöht ihn und gibt dann den neuen Wert zurück. Zum Beispiel:

CREATE FUNCTION NextOrderNumber() RETURNS INTEGER UNSIGNED NOT DETERMINISTIC
BEGIN
  DECLARE number INTEGER UNSIGNED;
  UPDATE Settings SET IntegerValue=LAST_INSERT_ID(IntegerValue+1) WHERE KeyName='NextOrderNumber';
  SET number=LAST_INSERT_ID();
  return number;
END

Hinweis: Kritisieren Sie diese Funktion nicht. Ich weiß, dass sie Mängel aufweist. Sie dient nur zur Veranschaulichung.

Wir verwenden diese Funktion wie folgt:

INSERT INTO Orders(OrderNumber, ...)
SELECT NextOrderNumber(), ...

Wenn die binäre Protokollierung aktiviert ist, gibt CREATE FUNCTION folgenden Fehler aus:

Diese Funktion hat keine DETERMINISTIC, NO SQL oder READS SQL DATA in ihrer Deklaration und die binäre Protokollierung ist aktiviert (Sie könnten möchten die weniger sichere Variable log_bin_trust_function_creators verwenden).

Gibt es wirklich ein Problem mit der obigen Funktion, unabhängig davon, welches binlog_format eingestellt ist? Laut meiner Lektüre der relevanten MySQL-Seite kann ich keinen Grund erkennen, warum diese Funktion mit der Replikation inkompatibel wäre, entweder mit der binären Protokollierung auf ROW- oder STATEMENT-Ebene.

Wenn die Funktion sicher ist, ist es mir unangenehm, die globalen log_bin_trust_function_creators = 1 zu setzen. Ich möchte diese Prüfung nicht für alle Funktionen deaktivieren, nur für diese. Könnte ich stattdessen einfach die Funktion als NO SQL markieren, um die Warnung zu unterdrücken? Ich habe es versucht und es hat funktioniert. Wird dies ein Problem verursachen?

15
richb

Ich habe gegoogelt und hier bin ich. Ich habe einen Weg gefunden:

SET GLOBAL log_bin_trust_function_creators = 1;

Aber seien Sie vorsichtig, es kann für die Datenwiederherstellung oder Replikation unsicher sein ...

25
SpiderWan

Nach meinem Verständnis kann es zu Problemen bei der Datenwiederherstellung oder -replikation kommen

Ref: http://dev.mysql.com/doc/refman/5.0/de/stored-programs-logging.html

MySQL 5.0.6: Anweisungen, die gespeicherte Routinen und CALL-Anweisungen erstellen, werden protokolliert. Gespeicherte Funktionsaufrufe werden protokolliert, wenn sie in Anweisungen auftreten, die Daten aktualisieren (weil diese Anweisungen protokolliert werden).

Funktionsaufrufe werden jedoch nicht protokolliert, wenn sie in Anweisungen wie SELECT auftreten, die keine Daten ändern, selbst wenn eine Datenänderung innerhalb einer Funktion selbst erfolgt. Dies kann zu Problemen führen.

Unter bestimmten Umständen können Funktionen und Prozeduren unterschiedliche Auswirkungen haben, wenn sie zu unterschiedlichen Zeiten oder auf unterschiedlichen (Master- und Slave-) Computern ausgeführt werden, und daher für die Datenwiederherstellung oder -replikation unsicher sein.

Z.B.

CREATE FUNCTION myfunc () RETURNS INT DETERMINISTIC
BEGIN
  INSERT INTO t (i) VALUES(1);
  RETURN 0;
END;

SELECT myfunc();

Wenn eine gespeicherte Funktion in einer Anweisung wieSELECTaufgerufen wird, die keine Daten ändert, wird die Ausführung der Funktion nicht in das Binärprotokoll geschrieben, auch wenn die Funktion selbst Daten ändert. Dieses Protokollierungsverhalten kann Probleme verursachen. Angenommen, eine Funktion myfunc() ist wie oben definiert.

6
Rikin Patel

Es gibt zwei Möglichkeiten, dies zu beheben:

Führen Sie in der MySQL-Konsole Folgendes aus:

SET GLOBAL log_bin_trust_function_creators = 1;

Fügen Sie der Konfigurationsdatei mysql.ini Folgendes hinzu:

log_bin_trust_function_creators = 1

Die Einstellung lockert die Prüfung auf nicht deterministische Funktionen. Nicht deterministische Funktionen sind Funktionen, die Daten modifizieren (d. H. Anweisungen aktualisieren, einfügen oder löschen). Weitere Informationen finden Sie hier.

Bitte beachten Sie, dass diese Einstellung nicht gilt, wenn die binäre Protokollierung NICHT aktiviert ist.

1
Wale

Überlegen Sie, was in das Binärlog geschrieben wird.

Sie können nicht sicherstellen, dass für einen auf einem Master erstellten Auftrag dieselbe Sequenz generiert wird, wenn die Transaktion auf einem Slave oder, was wahrscheinlicher ist, von einem anderen Master im Cluster ausgeführt wird. z.B.

 0) Node 1 and Node 2 are in sync, NextOrderNumber=100
 1) Node 1 receives insert statement wrt order from customer A and assigns 
    order number 100, changes its NextOrderNumber to 101
 2) Node 1 writes the settings update to the log
 3) Node 1 writes the insert statement to the log
 4) Node 2 processes for customer B, asigns order number 100 and increments
 5) Node 2 writes the settings update from to the log
 6) Node 2 writes the insert statement to the log
 7) Nodes 2 reads settings update from the log @2 
         - Its NextOrderNumber is now 102
 8) Node 2 reads insert from log @3, tries to apply it but it fails 
         due to duplicate key
 9) Node 1 reads the update @5 - Its nextOrderNumber is also now 102
 10) Node1 reads insert from log @6 - 
         but this fails due to duplicate key

Jetzt beziehen sich die Bestellungen 100 auf den 2 Knoten auf unterschiedliche Daten, und es gibt keine Bestellung 101.

Es gibt einen Grund, warum viele Funktionen hinzugefügt wurden, um das Verhalten von auto_increment-Variablen zu ändern.

Wenn Sie die Einfügung in eine Prozedur einbinden, die einen Wert aus dem Sequenzgenerator abruft und in die Einfügungsanweisung einbettet, wird das unmittelbare Problem behoben. Sie müssen jedoch überlegen, wie Sie vermeiden, dieselbe Nummer zweimal mit unterschiedlichen Datenbankknoten zuzuweisen.

0
symcbean

Könnte ich stattdessen einfach die Funktion als NO SQL markieren, um die Warnung zu unterdrücken? Ich habe es versucht und es hat funktioniert. Wird dies ein Problem verursachen?

Nach diesem Mysql doc :

Die Bewertung der Art einer Funktion basiert auf der „Ehrlichkeit“ des Erstellers: MySQL überprüft nicht, ob eine als DETERMINISTIC deklarierte Funktion frei von Anweisungen ist, die nicht deterministische Ergebnisse liefern.

Also liegt es an dir. Wenn Sie sicher sind, dass die Methode kein Problem verursacht ...

0
matof