Niezsynchronizowane polecenia; nie możesz teraz uruchomić tego polecenia

94

Próbuję wykonać mój kod PHP, który wywołuje dwa zapytania MySQL za pośrednictwem mysqli i wyświetla komunikat o błędzie „Polecenia nie są zsynchronizowane; nie można teraz uruchomić tego polecenia”.

Oto kod, którego używam

<?php
$con = mysqli_connect("localhost", "user", "password", "db");
if (!$con) {
    echo "Can't connect to MySQL Server. Errorcode: %s\n". Mysqli_connect_error();
    exit;
}
$con->query("SET NAMES 'utf8'");
$brand ="o";
$countQuery = "SELECT ARTICLE_NO FROM AUCTIONS WHERE upper(ARTICLE_NAME) LIKE % ? %";
if ($numRecords = $con->prepare($countQuery)) {
    $numRecords->bind_param("s", $brand);
    $numRecords->execute();
    $data = $con->query($countQuery) or die(print_r($con->error));
    $rowcount = $data->num_rows;
    $rows = getRowsByArticleSearch("test", "Auctions", " ");
    $last = ceil($rowcount/$page_rows);
}  else {

print_r($con->error);
}
foreach ($rows as $row) {
    $pk = $row['ARTICLE_NO'];
    echo '<tr>' . "\n";
    echo '<td><a href="#" onclick="updateByPk(\'Layer2\', \'' . $pk . '\')">'.$row['USERNAME'].'</a></td>' . "\n";
    echo '<td><a href="#" onclick="updateByPk(\'Layer2\', \'' . $pk . '\')">'.$row['shortDate'].'</a></td>' . "\n";
    echo '<td><a href="#" onclick="deleterec(\'Layer2\', \'' . $pk . '\')">DELETE RECORD</a></td>' . "\n";
    echo '</tr>' . "\n";
}
function getRowsByArticleSearch($searchString, $table, $max) {
    $con = mysqli_connect("localhost", "user", "password", "db");
    $recordsQuery = "SELECT ARTICLE_NO, USERNAME, ACCESSSTARTS, ARTICLE_NAME, date_format(str_to_date(ACCESSSTARTS, '%d/%m/%Y %k:%i:%s'), '%d %m %Y' ) AS shortDate FROM AUCTIONS WHERE upper(ARTICLE_NAME) LIKE '%?%' ORDER BY str_to_date(ACCESSSTARTS, '%d/%m/%Y %k:%i:%s')" . $max;
    if ($getRecords = $con->prepare($recordsQuery)) {
        $getRecords->bind_param("s", $searchString);
        $getRecords->execute();
        $getRecords->bind_result($ARTICLE_NO, $USERNAME, $ACCESSSTARTS, $ARTICLE_NAME, $shortDate);
        while ($getRecords->fetch()) {
            $result = $con->query($recordsQuery);
            $rows = array();
            while($row = $result->fetch_assoc()) {
                $rows[] = $row;
            }
            return $rows;
        }
    }
}

Próbowałem to przeczytać, ale nie jestem pewien, co robić. Czytałem o wynikach w sklepie i wynikach bezpłatnych, jednak nie miały one znaczenia podczas ich używania. Nie jestem pewien, w którym dokładnie momencie ten błąd jest spowodowany, i chciałbym wiedzieć, dlaczego jest on powodowany i jak go naprawić.

Przechodząc przez moje instrukcje debugowania, pierwsza pętla if dla countQuery nie została nawet wprowadzona z powodu błędu w mojej składni sql blisko near '% ? %'. Jeśli jednak po prostu wybiorę *zamiast próbować ograniczyć na podstawie klauzuli LIKE, nadal otrzymuję błąd braku synchronizacji polecenia.

Joshxtothe4
źródło

Odpowiedzi:

114

Nie możesz mieć dwóch jednoczesnych zapytań, ponieważ mysqli domyślnie używa niebuforowanych zapytań (w przypadku przygotowanych instrukcji; w przypadku wanilii jest odwrotnie mysql_query). Możesz pobrać pierwszą z nich do tablicy i przechodzić przez nią w pętli, lub powiedzieć mysqli, aby buforowała zapytania (używając $stmt->store_result()).

Zobacz tutaj, aby uzyskać szczegółowe informacje.

HoLyVieR
źródło
3
Zgadzam się, mysqli ma trochę uszkodzony mózg. To ma zrobić dobry uczynek z kierowcą PDO mysql chociaż.
17
Państwo może mieć dwóch jednoczesnych zapytań - wystarczy uruchomić $stmt->store_result();Myślę, że odpowiedź powinna uczynić to bardziej jasne.
Shadow
3
Wieki zajęło mi znalezienie tych informacji - nigdzie nie są one łatwe do wyświetlenia. Dzięki. Po prostu oddzielam moje zapytania, $select_stmt->close();aby je podzielić (nie jednoczesne, ale proceduralne
n34_panda
@flussence, Powiedziałeś, że „mysqli domyślnie używa niebuforowanych zapytań”. Jak więc możemy to zrobić inaczej?
Pacerier
1
Wiem, że wydaje się to dziwne, ale miałem ten błąd podczas wykonywania zapytania z mysqli_query naruszającym klucz obcy ... więc jeśli zdarzy się to komukolwiek, sprawdź
dokładnie
35

Rozwiązałem ten problem w mojej aplikacji C - oto jak to zrobiłem:

  1. Cytowanie z forów mysql:

    Ten błąd pojawia się, gdy zakończysz zapytanie za pomocą separatora średnika wewnątrz aplikacji . Chociaż wymagane jest zakończenie zapytania za pomocą separatora średnika podczas wykonywania go z wiersza poleceń lub w przeglądarce zapytań, usuń separator z zapytania wewnątrz aplikacji.

  2. Po uruchomieniu zapytania i zajęciu się wynikami [C API: mysql_store_result()] iteruję po wszelkich dalszych potencjalnie oczekujących wynikach, które pojawiają się poprzez wykonanie wielu instrukcji SQL, takich jak dwie lub więcej instrukcji select (z powrotem do tyłu bez zajmowania się wynikami).

    Faktem jest, że moje procedury nie zwracają wielu wyników, ale baza danych nie wie tego, dopóki nie wykonam: [C API: mysql_next_result()]. Robię to w pętli (na dokładkę), dopóki nie zwróci wartości niezerowej. Wtedy bieżący program obsługi połączenia wie, że można wykonać kolejne zapytanie (buforuję moje programy obsługi, aby zminimalizować narzut połączenia).

    Oto pętla, której używam:

    for(; mysql_next_result(mysql_handler) == 0;) 
      /* do nothing */;
    

Nie znam PHP, ale na pewno ma coś podobnego.

tracy.brown
źródło
12
To było to dla mnie. W PHP właśnie dodałem: while (mysqli_next_result ($ con));
Josh
Dzięki za odpowiedź, która rozwiązała mój problem. Usunąłem ogranicznik i działa. Nie zwolniłem (pobrałem) ani nie zapisałem wyników, ale zamknąłem kursor i ponownie zbudowałem po zakończeniu jednego zapytania.
Chen Xie
@Josh, jak to zrobić w starszym mysqlrozszerzeniu?
Pacerier
1
Usunięcie średnika na końcu zapytania rozwiązało problem „Polecenia niezsynchronizowane; nie można teraz uruchomić tego polecenia” podczas korzystania z Python MySQLdb.
Genome
17

Dzisiaj miałem ten sam problem, ale tylko podczas pracy z procedurą składowaną. To sprawia, że ​​zapytanie zachowuje się jak złożone zapytanie, więc przed wykonaniem kolejnego zapytania należy „skonsumować” inne dostępne wyniki.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
Stalin Beltran
źródło
Jest to ważna kwestia: procedury składowane zwracają zestaw wyników wykraczający poza dowolny zestaw wyników, który może wygenerować kod w SP. Musisz sobie z tym poradzić lub otrzymać ten błąd: stackoverflow.com/a/2315229/4495850
Richard
11

Wywołuję tę funkcję za każdym razem przed użyciem $ mysqli-> query Działa również z procedurami składowanymi.

function clearStoredResults(){
    global $mysqli;

    do {
         if ($res = $mysqli->store_result()) {
           $res->free();
         }
        } while ($mysqli->more_results() && $mysqli->next_result());        

}
Juergen
źródło
6

Kiedyś użyłeś

stmt->execute();

Ci MOŻE zamknąć go użyć innego zapytania.

stmt->close();

Ten problem polował na mnie godzinami. Miejmy nadzieję, że to naprawi twoje.

Carl James
źródło
2
Zamknięcie oświadczenia nie jest konieczne. Jak @stalinbeltran odpowiedział powyżej, musimy „skonsumować” wynik wypowiedzi przed przygotowaniem kolejnego. Więc $stmt1->execute(); $stmt2=$conn->prepare(...)dałby ten błąd, ale $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)działałby dobrze.
Jay Dadhania
Bro, pomogło mi, dziękuję. dla każdego, kto mówi to i owo, użyłem mysqli_prepare dwa razy przed zamknięciem pierwszego. To działa.
Abhinash Majhi
3

Używam CodeIgniter. Jeden serwer OK ... ten prawdopodobnie starszy ... W każdym razie używając

$this->db->reconnect();

Naprawione.

Norman
źródło
7
Jak to rozwiązuje problem?
Jeremy J Starcher,
4
@Norman, to nie „rozwiązuje” problemu. Po prostu unika tego, odrzucając całe połączenie i łącząc się ponownie. To nie ma żadnego sensu z punktu widzenia wydajności.
Pacerier
1

Problemem jest biblioteka C klienta MySQL, na której jest zbudowana większość interfejsów API MySQL. Problem polega na tym, że biblioteka C nie obsługuje jednoczesnego wykonywania zapytań, więc wszystkie interfejsy API zbudowane na niej również nie obsługują. Nawet jeśli używasz niebuforowanych zapytań. Jest to jeden z powodów, dla których napisano asynchroniczne API MySQL. Komunikuje się bezpośrednio z serwerem MySQL przy użyciu protokołu TCP i drutu protokołu nie obsługuje jednoczesnych zapytań.

Twoim rozwiązaniem jest albo zmodyfikowanie algorytmu, aby nie trzeba było mieć obu jednocześnie w toku, albo zmiana ich na zapytania buforowane, co jest prawdopodobnie jednym z pierwotnych powodów ich istnienia w bibliotece C (drugim jest zapewniają rodzaj kursora).

staticsan
źródło
1
Nie muszę mieć obu jednocześnie w toku, cieszę się, że countQuery zakończy się całkowicie przed moim drugim zapytaniem, ale nie jestem pewien, jak zatrzymać countQuery w toku
Nie pobierasz żadnych danych z countQuery, dlatego nadal jest w toku. Pobierz wszystkie wiersze lub zmień go na SELECT COUNT (ARTICLE_NO) i pobierz ten wiersz. Wtedy zostanie uruchomione drugie zapytanie.
staticsan
Kiedy mówisz „asynchroniczny interfejs MySQL API”, do którego interfejsu API się odnosisz? Nie wyciągam też wniosków. Ten „problem” można naprawić bez konieczności asynchronicznego interfejsu API.
Pacerier
1
Szczerze mówiąc @Pacerier nie jestem już pewien, co miałem na myśli! Wiele wydarzyło się w ciągu sześciu lat w łączności MySQL, więc cokolwiek myślałem, że miałem na myśli, prawdopodobnie zostało zmienione i / lub włączone do innego nowego sterownika.
staticsan
1

Aby rozwiązać ten problem, musisz zapisać dane wyników przed ich użyciem

$numRecords->execute();

$numRecords->store_result();

to wszystko

Nader Ben Mabrouk
źródło
1

Inna przyczyna: store_result () nie może zostać wywołana dwukrotnie.

Na przykład w poniższym kodzie drukowany jest błąd 5.

<?php

$db = new mysqli("localhost", "something", "something", "something");

$stmt = $db->stmt_init();
if ($stmt->error) printf("Error 1 : %s\n", $stmt->error);

$stmt->prepare("select 1");
if ($stmt->error) printf("Error 2 : %s\n", $stmt->error);

$stmt->execute();
if ($stmt->error) printf("Error 3 : %s\n", $stmt->error);

$stmt->store_result();
if ($stmt->error) printf("Error 4 : %s\n", $stmt->error);

$stmt->store_result();
if ($stmt->error) printf("Error 5 : %s\n", $stmt->error);

(Może to nie mieć znaczenia dla oryginalnego przykładowego kodu, ale może być istotne dla osób poszukujących odpowiedzi na ten błąd).

David G.
źródło
1

Oto jaki był MÓJ PROBLEM !!!

Wiązanie parametrów było „dynamiczne”, więc miałem zmienną, która ustawia parametry danych, aby użyć bind_param . Więc ta zmienna była błędna, ale zamiast zgłaszać błąd, taki jak „nieprawidłowe dane parametrów”, wyświetla komunikat „niezsynchronizowany bla bla bla”, więc byłem zdezorientowany ...

Ari Waisberg
źródło
0

Myślę, że problem polega na tym, że tworzysz nowe połączenie w funkcji, a następnie nie zamykasz go na końcu. Dlaczego nie spróbujesz przekazać istniejącego połączenia i ponownie go użyć?

Inną możliwością jest to, że wracasz w połowie czasu pobierania pętli. Nigdy nie kończysz tego zewnętrznego pobierania.

Paul Tomblin
źródło
1
Jeśli ustawię $ con jako globalny (co jest złą praktyką, ale powinno działać tak, jak opisujesz) nadal mam ten sam błąd.
1
Nie sądzę, że połączenie globalne jest złą praktyką
Mathieu J.
0

Sprawdź, czy poprawnie wpisujesz wszystkie parametry. Zgłasza ten sam błąd, jeśli liczba parametrów zdefiniowanych, a następnie przekazanych do funkcji jest inna.

Mixtelf
źródło
0

Nie jest to związane z pierwotnym pytaniem, ale miałem ten sam komunikat o błędzie i ten wątek jest pierwszym hitem w Google i zajęło mi trochę czasu, zanim zrozumiałem problem, więc może być przydatny dla innych:

NIE używam mysqli, nadal używam mysql_connect. Miałem kilka prostych zapytań, ale JEDNE zapytanie spowodowało, że wszystkie inne zapytania zawiodły w tym samym połączeniu.

Używam mysql 5.7 i php 5.6. Miałem tabelę z typem danych „JSON”. oczywiście moja wersja php nie rozpoznała wartości zwracanej przez mysql (php po prostu nie wiedział, co zrobić z formatem JSON, ponieważ wbudowany moduł mysql był zbyt stary (przynajmniej tak mi się wydaje))

na razie zmieniłem JSON-Field-Type na Text (na razie nie potrzebuję natywnej funkcjonalności mysql JSON) i wszystko działa dobrze

mech
źródło
0

Jeśli używasz zbuforowanego lub niebuforowanego zestawu wyników do pobierania danych, najpierw musisz po prostu wyczyścić pobrane dane z pamięci, po pobraniu wszystkich danych . Ponieważ nie możesz wykonać innej procedury MYSQL na tym samym połączeniu, dopóki nie wyczyścisz pobranej pamięci. Dodaj poniższą funkcję na prawym końcu skryptu, aby rozwiązać problem

$numRecords->close(); or $numRecords->free(); // This clears the referencing memory, and will be ready for the next MYSQL fetch

Odniesienie z dokumentacji PHP

Kaz
źródło
1
Jeśli nie potrzebujesz niektórych rekordów, to w pierwszej kolejności nie powinieneś ich wybierać. Zamiast po prostu ich uwolnić, po prostu w ogóle ich nie wybieraj. A jeśli tak nie jest i pobrałeś wszystkie wybrane rekordy, to w ogóle nie będzie takiego błędu, jak również nie ma potrzeby wywoływania funkcji close () lub free (). Jeśli chodzi o procedury składowane, istnieje mniej barbarzyńska metoda, opisana w odpowiedziach powyżej
Your Common Sense
0

Napotkałem ten błąd za pomocą Doctrine DBAL QueryBuilder.

Utworzyłem zapytanie za pomocą QueryBuilder, które używa podselekcji kolumn, również utworzonych za pomocą QueryBuilder. Podselekcje zostały utworzone tylko przez $queryBuilder->getSQL()i nie zostały wykonane. Wystąpił błąd podczas tworzenia drugiej podselekcji. Dzięki tymczasowemu wykonaniu każdej podselekcji $queryBuilder->execute()przed użyciem $queryBuilder->getSQL()wszystko działało. To tak, jakby połączenie $queryBuilder->connectionpozostawało w nieprawidłowym stanie do utworzenia nowego kodu SQL przed wykonaniem aktualnie przygotowanego kodu SQL, pomimo nowej instancji QueryBuilder na każdej podselekcji.

Moim rozwiązaniem było napisanie podselekcji bez QueryBuilder.

Fabian Picone
źródło
0

Używam ODBC i ta poprawka działa dla mnie: ODBC -> zakładka Systemowe DSN -> kliknij dwukrotnie, aby skonfigurować moje źródło danych -> szczegóły -> zakładka Kursory -> Odznacz [Nie buforuj wyników kursorów tylko do przodu] - > kliknij OK

Teemo
źródło
0

Często trafiam na ten błąd i zawsze, gdy uruchamiam procedurę składowaną, debuguję w phpmyadmin lub SQL Workbench (pracuję w php łącząc się z mysqli).

Błąd wynika z faktu, że debugowanie polega na wstawianiu instrukcji SELECT w strategicznych punktach kodu, aby poinformować mnie o stanie zmiennych itp. Uruchamianie procedury składowanej, która generuje wiele zestawów wyników w tych środowiskach klienckich, jest w porządku, ale generuje " Polecenia niezsynchronizowane ”błąd podczas wywołania z php. Rozwiązaniem jest zawsze wykomentowanie lub usunięcie zaznaczeń debugowania, aby procedura miała tylko jeden zestaw wyników.

Nikkorian
źródło
0

Tak dla odniesienia miałem ten problem z mieszaniem obu multi_queryiw querytym samym kodzie:

$connection->multi_query($query);
...
$connection->query($otherQuery);

Które z tego, co przeczytałem, miały nieużywane wyniki, powodując w ten sposób wspomniany błąd.

Rozwiązałem to za pomocą pętli pochłaniającej wszystkie wyniki multi_query:

$connection->multi_query($query);
while ($connection->next_result()); // <--- solves the problem
...
$connection->query($otherQuery);

W moim przypadku wszystkie zapytania w multi_querymiejscu wstawiają, więc nie interesowały mnie same wyniki.

Isac
źródło
-1

Mój problem polegał na tym, że najpierw korzystałem z instrukcji przygotowania, a następnie używałem zapytania mysqli na tej samej stronie i otrzymywałem błąd „Polecenia nie są zsynchronizowane; nie możesz teraz uruchomić tego polecenia”. Błąd pojawił się dopiero wtedy, gdy korzystałem z kodu, który miał przygotować instrukcję.

Zamknąłem pytanie. i zadziałało.

mysqli_stmt_close ($ stmt);

Mój kod

get_category.php (tutaj przy użyciu instrukcji przygotowania)

    <?php


    global $connection;
    $cat_to_delete =    mysqli_real_escape_string($connection, $_GET['get'] );

    $sql = "SELECT category_name FROM categories WHERE category_id = ? ;";


    $stmt = mysqli_stmt_init($connection);

    if (!mysqli_stmt_prepare($stmt, $sql))
        $_SESSION['error'] = "Error at preaparing for deleting query. mysqli_stmt_error($stmt) ." & redirect('../error.php');

    mysqli_stmt_bind_param($stmt, 's', $cat_to_delete);

    if (!mysqli_stmt_execute($stmt))
        $_SESSION['error'] = "ERror at executing delete category ".mysqli_stmt_error($stmt) &
            redirect('../error.php');


    mysqli_stmt_bind_result($stmt, $cat_name);

    if (!mysqli_stmt_fetch($stmt)) {
        mysqli_stmt_error($stmt);
    }



    mysqli_stmt_free_result($stmt);
    mysqli_stmt_close($stmt);

admin_get_category_body.php (tutaj mysqli)

        <?php

        if (isset($_GET['get']) && !empty($_GET['get']) )
        {
            include 'intodb/edit_category.php';
        }


        if (check_method('get') && isset($_GET['delete']) )
        {
            require 'intodb/delete_category.php';
        }


        if (check_method('get') && isset($_GET['get']) )
        {
            require 'intodb/get_category.php';
        }


        ?>

        <!--            start: cat body          -->

        <div     class="columns is-mobile is-centered is-vcentered">
            <div class="column is-half">
                <div   class="section has-background-white-ter box ">


                    <div class="has-text-centered column    " >
                        <h4 class="title is-4">Ctegories</h4>
                    </div>

                    <div class="column " >


                        <?php if (check_method('get') && isset($_GET['get'])) {?>
                        <form action="" method="post">
                            <?php } else {?>
                            <form action="intodb/add_category.php" method="post">
                                <?php } ?>

                                <label class="label" for="admin_add_category_bar">Add Category</label>
                                <div class="field is-grouped">

                                    <p class="control is-expanded">

                                        <?php if (check_method('get') && isset($_GET['get'])) {?>

                                            <input id="admin_add_category_bar" name="admin_add_category_bar_edit" class="input" type="text" placeholder="Add Your Category Here" value="<?php echo $cat_name; ?>">

                                            <?php


                                            ?>
                                        <?php } else {?>
                                            <input id="admin_add_category_bar" name="admin_add_category_bar" class="input" type="text" placeholder="Add Your Category Here">

                                        <?php } ?>
                                    </p>
                                    <p class="control">
                                        <input type="submit" name="admin_add_category_submit" class="button is-info my_fucking_hover_right_arrow" value="Add Category">
                                    </p>
                                </div>
                            </form>


                            <div class="">

                                <!--            start: body for all posts inside admin          -->


                                <table class="table is-bordered">
                                    <thead>
                                    <tr>
                                        <th><p>Category Name</p></th>
                                        <th><p>Edit</p></th>
                                        <th><p>Delete</p></th>
                                    </tr>
                                    </thead>

                                    <?php

                                    global $connection;
                                    $sql = "SELECT * FROM categories ;";

                                    $result = mysqli_query($connection, $sql);
                                    if (!$result) {
                                        echo mysqli_error($connection);
                                    }
                                    while($row = mysqli_fetch_assoc($result))
                                    {
                                        ?>
                                        <tbody>
                                        <tr>
                                            <td><p><?php echo $row['category_name']?></p></td>
                                            <td>
                                                <a href="admin_category.php?get=<?php echo $row['category_id']; ?>" class="button is-info my_fucking_hover_right_arrow" >Edit</a>

                                            </td>

                                            <td>
                                                <a href="admin_category.php?delete=<?php echo $row['category_id']; ?>" class="button is-danger my_fucking_hover_right_arrow" >Delete</a>

                                            </td>
                                        </tr>


                                        </tbody>
                                    <?php }?>
                                </table>

                                <!--           end: body for all posts inside admin             -->




                            </div>

                    </div>
                </div>


            </div>

        </div>
        </div>

Coś, co właśnie przyszło mi do głowy, ponownie dodaję zmienną połączenia za pośrednictwem globalnego połączenia $ ;. Myślę więc, że po zakończeniu instrukcji przygotowania za pomocą mysqli_stmt_close ($ stmt) uruchamia się cały nowy zestaw zapytań; a także dodaję te pliki i inne rzeczy przez include

Mahad Ali
źródło
get_category.php (tutaj przy użyciu instrukcji przygotowania) pastebin.com/BiWysdYz admin_get_category_body.php (tutaj mysqli) pastebin.com/Pwm30icm Uwaga: Nie można wysłać całego kodu z powodu ograniczeń
Mahad Ali
Coś, co właśnie przyszło mi do głowy, ponownie dodaję zmienną połączenia za pośrednictwem globalnego połączenia $ ;. Myślę więc, że po zakończeniu instrukcji przygotowania za pomocą mysqli_stmt_close ($ stmt) uruchamia się cały nowy zestaw zapytań; a także dodaję te pliki i inne rzeczy przez include.
Mahad Ali
-1

To jest stare pytanie, ale żadna z opublikowanych odpowiedzi nie zadziałała w moim przypadku, odkryłem, że w moim przypadku miałem selekcje i aktualizacje w tabeli w mojej procedurze składowanej, ta sama tabela miała wyzwalacz aktualizacji, który był wyzwalany i sengowanie procedurę w nieskończoną pętlę. Po znalezieniu błędu błąd zniknął.

shelbypereira
źródło