2013-03-11 25 views
10

Używam mysql.connector do wykonywania operacji SQL. Mam krótkie skrypty, które wykonuje następujące operacje (łańcuchy) na kursor z cursor.execute(...):Nieczytelny wynik MySQL z Pythonem

"use {}".format(db) 

"show tables" 

command = """ 
ALTER TABLE Object DROP PRIMARY KEY; 
ALTER TABLE Object ADD `id` bigint(20) NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST; 
ALTER TABLE Object ADD INDEX (`uid`);""" 

W iteracje skryptów w ciągu kilku bazach db.

Problem polega na tym, że w pewnym momencie pojawia się błąd "Nieprzeczytane znalezione wyniki". Wydaje się, że po uruchomieniu skryptu, w pewnym momencie "use mydb" zwraca wynik (cursor._have_result = True), kiedy nie oczekiwałem jednego. Dziwne jest to, że jeśli ponownie uruchomię pełny skrypt, uruchomi się on nieco dłużej z większą ilością baz danych, dających ten sam błąd później.

Czy możesz zaproponować sposób rozwiązania lub zbadania tego problemu? Czy jest coś, co mogę zrobić, aby zapobiec "nieprzeczytanym wynikom"?

PS: Po ponownym uruchomieniu skryptu polecenia ALTER nie powiodą się dla baz danych, które zostały już wykonane. Nie jestem pewien, czy to powoduje problemy.

+0

Can polecasz ten http://geert.vanderkelen.org/buffering-results-with-mysql-connectorpython/? Nie wiem, czy to z tego samego powodu, dla którego pojawia się błąd "Nieprzeczytane znalezione wyniki". – Angel

+0

Nie jestem pewien, czy ten sam problem, ale stwierdziłem, że wydanie polecenia składającego się z kilku ciężkich długotrwałych zapytań może spowodować problem podobny do twojego. Spróbuj podzielić 'polecenie' w trzech osobnych instrukcjach. – dmg

+0

@DJV: Rozdzieliłem komendy i teraz działało bez błędów. Dzięki! Nie wiem, jak to wyjaśnić. – Gerenuk

Odpowiedz

12

Używanie złącza MySQL/Python, Nieczytane wyniki znalezione mogą się zdarzyć, gdy obiekt połączenia zostanie użyty w różnych miejscach bez odczytywania wyniku. To nie jest coś, czym można się obejść. Możesz użyć buffered option, aby natychmiast odczytać wynik.

Jak wspomniano w komentarzach, najlepiej podzielić instrukcje i wykonać je oddzielnie.

Jeśli chcesz wykonać wiele instrukcji, musisz użyć metody multi=True option for the MySQLCursor.execute() (od wersji Connector/Python v1.0.4). W rzeczywistości, jeśli nie użyjesz opcji multi i wyślesz wiele instrukcji, wystąpi błąd InterfaceError. (Ja podejrzewam błąd również tutaj ..)

Uwagi dodatkowe

  • Zamiast wykonywania przydatności do użycia polecenia do zmiany bazy danych, można MySQLConnection.database property.
  • Jesteś najlepsza grupa zmienia się w jednej instrukcji ALTER TABLE, takie jak ten:

    ALTER TABLE t1 DROP PRIMARY KEY, ADD id INT NOT NULL AUTO_INCREMENT KLUCZ PIERWSZY, ADD INDEX (C1)

+1

Jak można uniknąć tego błędu bez opcji 'buforowanej'? AFAIK czytasz wyniki używając 'MySQLCursor.description' - czy istnieje inna metoda, którą powinienem użyć zamiast tego? – sorbet

+0

@sorbet: Jedynym sposobem jest zamknięcie połączenia i ponowne połączenie. Nie, wyniki nie są czytane podczas pobierania opisu. – geertjanvdk

+1

dlaczego dokładnie nie można odczytać połączenia MySQL/python * discard *, gdy nie są buforowane?buforowanie to ogromny problem z wydajnością, ale bez możliwości odrzucenia pozostałych danych nie można go wyłączyć. OurSQL nie ma tego problemu. – zzzeek