Mysql: Sitzungsvariablen können nicht verwendet werden?

Erstellt am 23. Jan. 2014  ·  7Kommentare  ·  Quelle: go-sql-driver/mysql

wie man wiederholt
db.Query ("set @ a = 1")
db.Query ("select @a")

return null

Dies scheint darauf zurückzuführen zu sein, dass das Laufwerk bei der Ausführung von "select @a" eine neue Sitzung auf dem MySQL-Server erstellt. Dies führt dazu, dass Sitzungsvariablen nicht verwendet werden können.

Ist der Mechanismus von database / sql oder github.com/go-sql-driver/mysql betroffen?

databassql issue question

Hilfreichster Kommentar

In Ihrem Beispielcode, der das Binlog-Format gedruckt hat, haben Sie geschrieben

trx ,: = db.Begin ()
db.Query ("set binlogformat = row")
Zeilen, _: = db.Query ("select @@ binlog_format")

Sie können dort nicht auf die Variable db zugreifen. Sie müssen dies stattdessen tun:

trx, err: = db.Begin ()
trx.Query (...)

Beachten Sie, dass ich mit trx abfrage, nicht mit db.

Möglicherweise müssen wir im Tutorial klarere Beispiele dafür geben
"Sitzungen" mit Transaktionen, die dies hervorheben. Wenn das Tutorial nicht ist
klar für Sie, bitte melden Sie einen Fehler an
https://github.com/VividCortex/go-database-sql-tutorial/issues

Alle 7 Kommentare

Mit Ihrem bereitgestellten Beispielcode sind zwei Dinge falsch:
1) db.Query gibt rows das geschlossen oder vollständig gelesen werden muss (was es implizit schließt). Andernfalls wird die Verbindung blockiert und kann nicht für andere Abfragen wiederverwendet werden.
2) Wie Sie bereits vermutet haben, erstellt die 2. db.Query in den meisten Fällen eine neue Sitzung, da nicht garantiert wird, dass sie auf derselben Verbindung ausgeführt wird. Derzeit besteht die einzige Möglichkeit, eine Verbindung über die Datenbank- / SQL-Schnittstelle von Go zu reservieren, in der Verwendung von Transaktionen: http://golang.org/pkg/database/sql/#DB.Begin

Ich würde Ihnen empfehlen, das Datenbank- / SQL-Tutorial unter http://go-database-sql.org/ zu lesen.

Es kann eine neue Sitzung erstellen, es kann dieselbe verwenden. Wir wissen es nicht, es hängt vollständig vom Pooling um database/sql und wir können nichts tun, um es zu ändern.

Sie können

  • Melden Sie ein Problem an, um Go Sitzungsunterstützung hinzuzufügen, und hoffen Sie, dass es schnell hinzugefügt wird
  • Tun Sie dies in einer Transaktion (die für alle Abfragen dieselbe Verbindung verwendet).
  • Verwenden Sie den Treiber ohne database/sql
  • Verwenden Sie unsicher, um die Verbindung zu extrahieren
  • Schreiben Sie Ihre Abfragen neu, damit Variablen auf SELECT initialisiert werden

Mein Rezept für das letzte:

SET <strong i="17">@row</strong> := 0;
SELECT <strong i="18">@row</strong> := <strong i="19">@row</strong> + 1, * FROM mytable;

wird

SELECT <strong i="23">@row</strong> := <strong i="24">@row</strong> + 1, t.* FROM (SELECT <strong i="25">@row</strong> := 0) cnt JOIN mytable t;

Es können jedoch nicht alle Anweisungen in eine einzelne Anweisung geschrieben werden.
wie

   db, _ := sql.Open("mysql", connect_string)

   trx, _:= db.Begin()
   db.Query("set binlog_format=row")

   rows, _ := db.Query("select @@binlog_format")
   for rows.Next() {
     var v string
     rows.Scan(&v)
     fmt.Println(v)
   }   
   rows.Close()

   trx.Commit()
   db.Close()

Es wird "gemischt" gedruckt, was der globale Wert ist.

Für Comman-Benutzer sieht es wie ein Fehler aus.
Obwohl es an der Datenbank / SQL liegt, gibt es etwas, das getan werden kann, um mit einem solchen Fall umzugehen?

Was meinst du mit Arnehormann unter "Treiber ohne Datenbank / SQL verwenden"? Erstellen Sie faild, ohne dieses Paket zu importieren

@tbdingqi Nein, nicht alle können in eine einzige Anweisung geschrieben werden. Aber einige der SET Probleme können auf diese Weise gelöst werden.

Für einen normalen Benutzer sieht es wie ein Fehler aus:
Wir können nichts tun und etwas, das Sie tun können. Ich habe diese Dinge aufgelistet.
Wenn etwas anderes getan werden könnte, hätten wir es getan oder würden es tun, sobald wir können.
Bitte lesen Sie das Tutorial, mit dem Julien verlinkt ist. Es beschreibt die Einschränkungen der API ziemlich gut.

Der Import: Sie können stattdessen import "github.com/go-sql-driver/mysql" verwenden

import (
  "database/sql"
  _  "github.com/go-sql-driver/mysql"
)

und sprechen Sie direkt mit dem Fahrer ohne database/sql .

In Ihrem Beispielcode, der das Binlog-Format gedruckt hat, haben Sie geschrieben

trx ,: = db.Begin ()
db.Query ("set binlogformat = row")
Zeilen, _: = db.Query ("select @@ binlog_format")

Sie können dort nicht auf die Variable db zugreifen. Sie müssen dies stattdessen tun:

trx, err: = db.Begin ()
trx.Query (...)

Beachten Sie, dass ich mit trx abfrage, nicht mit db.

Möglicherweise müssen wir im Tutorial klarere Beispiele dafür geben
"Sitzungen" mit Transaktionen, die dies hervorheben. Wenn das Tutorial nicht ist
klar für Sie, bitte melden Sie einen Fehler an
https://github.com/VividCortex/go-database-sql-tutorial/issues

@xaprb guter Fang, ich habe den Tx-Missbrauch verpasst.

Diese Methode funktioniert nicht für Variablen wie sql_log_bin .
MySQL selbst gibt einen Fehler aus:
ERROR 1694 (HY000): Cannot modify @@session.sql_log_bin inside a transaction

Gibt es eine Möglichkeit, diese Variable für *sql.DB einzurichten?

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen