Команды не синхронизированы; вы не можете запустить эту команду сейчас

94

Я пытаюсь выполнить свой PHP-код, который вызывает два запроса MySQL через mysqli, и получаю сообщение об ошибке «Команды не синхронизированы; вы не можете запустить эту команду сейчас».

Вот код, который я использую

<?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;
        }
    }
}

Я пробовал читать об этом, но не знаю, что делать. Я читал о результатах магазина и бесплатном результате, однако они не повлияли на их использование. Я не уверен, в какой именно момент возникает эта ошибка, и хотел бы знать, почему она возникает и как ее исправить.

Судя по моим отладочным инструкциям, первый цикл if для countQuery даже не вводится из-за ошибки в моем синтаксисе sql рядом '% ? %'. Однако, если я просто выберу *вместо попытки ограничения на основе предложения LIKE, я все равно получу ошибку рассинхронизации команды.

Joshxtothe4
источник

Ответы:

114

Вы не можете иметь два одновременных запроса, потому что mysqli по умолчанию использует небуферизованные запросы (для подготовленных операторов; для vanilla все наоборот mysql_query). Вы можете либо извлечь первый из них в массив и пройти через него, либо указать mysqli для буферизации запросов (используя $stmt->store_result()).

Подробности смотрите здесь .

HoLyVieR
источник
3
Я согласен, mysqli немного поврежден. Тем не менее, он делает правильные вещи с драйвером mysql PDO.
17
У вас может быть два одновременных запроса - вам просто нужно выполнить, $stmt->store_result();я думаю, ваш ответ должен прояснить это.
Shadow
3
Мне потребовалось много времени, чтобы найти эту информацию - нигде она не отображается легко. Спасибо. Я просто разделяю свои запросы, $select_stmt->close();чтобы разделить их (не одновременные, а процедурные
n34_panda
@flussence, Вы заявили, что "mysqli по умолчанию использует небуферизованные запросы". Итак, как мы можем настроить его иначе?
Pacerier
1
Я знаю, что это кажется странным, но у меня была эта ошибка при выполнении запроса с mysqli_query, нарушающим внешний ключ ... поэтому, если это произойдет с кем-либо, дважды проверьте, что ваш запрос INSERT не нарушает какой-либо внешний ключ
lucaferrario
35

Я решил эту проблему в своем приложении C - вот как я это сделал:

  1. Цитата с форумов mysql:

    Эта ошибка возникает, когда вы завершаете свой запрос разделителем точки с запятой внутри приложения . Хотя при выполнении запроса из командной строки или в браузере запросов требуется завершить запрос разделителем точки с запятой, удалите разделитель из запроса внутри вашего приложения.

  2. После выполнения моего запроса и обработки результатов [C API: mysql_store_result()] я перебираю любые дальнейшие потенциально ожидающие результаты, которые возникают в результате выполнения нескольких операторов SQL, таких как два или более операторов выбора (последовательно без обработки результатов).

    Дело в том, что мои процедуры не возвращают несколько результатов, но база данных не знает этого, пока я не выполню: [C API: mysql_next_result()]. Я делаю это в цикле (для хорошей оценки), пока он не вернет ненулевое значение. Тогда текущий обработчик соединения знает, что можно выполнить другой запрос (я кэширую свои обработчики, чтобы минимизировать накладные расходы на соединение).

    Это цикл, который я использую:

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

Я не знаю PHP, но уверен, что в нем есть что-то подобное.

tracy.brown
источник
13
Это было для меня. В PHP я только что добавил: while (mysqli_next_result ($ con));
Джош
Спасибо за ответ, который решил мою проблему. Я удалил разделитель, и все работает. Я не освобождаю (извлекаю) и не сохраняю свои результаты, а закрываю курсор и перестраиваю после того, как закончу одну инструкцию запроса.
Chen Xie
@Josh, как это сделать в устаревшем mysqlрасширении?
Pacerier
1
Удаление точки с запятой в конце запроса устранило проблему «Команды не синхронизированы; вы не можете запустить эту команду сейчас» при использовании Python MySQLdb.
Genome
17

У меня сегодня была такая же проблема, но только при работе с хранимой процедурой. Это заставляет запрос вести себя как многопользовательский запрос, поэтому вам нужно «использовать» другие доступные результаты, прежде чем выполнять другой запрос.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
Сталин Бельтран
источник
Это важный момент: хранимые процедуры возвращают набор результатов сверх любого набора результатов, который может сгенерировать код в SP. Вы должны обработать это или получить эту ошибку: stackoverflow.com/a/2315229/4495850
Ричард
11

Я вызываю эту функцию каждый раз перед использованием $ mysqli-> query. Также работает с хранимыми процедурами.

function clearStoredResults(){
    global $mysqli;

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

}
Юрген
источник
6

Как только вы использовали

stmt->execute();

Вы МОЖЕТЕ закрыть его, чтобы использовать другой запрос.

stmt->close();

Эта проблема преследовала меня часами. Надеюсь, это исправит вашу.

Карл Джеймс
источник
2
Закрывать выписку не нужно. Как @stalinbeltran ответил выше, нам нужно «потреблять» результат одного оператора, прежде чем готовить другой. Итак, $stmt1->execute(); $stmt2=$conn->prepare(...)выдаст эту ошибку, но $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)будет работать нормально.
Джей Дадхания
Братан, это помогло мне, спасибо. Для всех, кто говорит то и это, я использовал mysqli_prepare два раза, прежде чем закрыть первый. Оно работает.
Абхинаш Маджхи
3

Я использую CodeIgniter. Один сервер ОК ... этот, вероятно, старше ... В любом случае, используя

$this->db->reconnect();

Починил это.

Норман
источник
7
Как это решить проблему?
Джереми Джей Старчер,
4
@Norman, это не "решает" проблему. Он просто избегает этого, отбрасывая все соединение и повторно подключаясь. Это вообще не имеет смысла с точки зрения производительности.
Pacerier
1

Проблема заключается в клиентской C-библиотеке MySQL, на которой построено большинство MySQL API. Проблема в том, что библиотека C не поддерживает одновременное выполнение запросов, поэтому все API, построенные на ее основе, также не поддерживают. Даже если вы используете небуферизованные запросы. Это одна из причин, по которой был написан асинхронный MySQL API. Он взаимодействует непосредственно с сервером MySQL с использованием протокола TCP и провод-протоколом делает поддержку одновременных запросов.

Ваше решение состоит в том, чтобы либо изменить алгоритм, чтобы вам не нужно было запускать оба одновременно, либо изменить их для использования буферизованных запросов, что, вероятно, является одной из исходных причин их существования в библиотеке C (другая - предоставить своего рода курсор).

статический
источник
1
Мне не нужно, чтобы оба выполнялись одновременно, я рад, что countQuery полностью завершится до моего второго запроса, но я не уверен, как остановить выполнение countQuery
Вы не получаете никаких данных из countQuery, поэтому он все еще «в процессе». Либо получите все строки, либо измените его на SELECT COUNT (ARTICLE_NO) и получите эту строку. Затем будет выполнен ваш второй запрос.
staticsan 08
Когда вы говорите «асинхронный MySQL API», какой API вы имеете в виду? Кроме того, я не понимаю вашего заключения. Эта «проблема» может быть устранена без необходимости использования асинхронного API.
Pacerier
1
Если честно, @Pacerier, я тоже не совсем понимаю, что имел в виду! За шесть лет с подключением к MySQL многое произошло, поэтому все, о чем я думал, вероятно, было переименовано и / или включено в какой-то другой новый драйвер.
staticsan
1

чтобы решить эту проблему, вы должны сохранить данные результатов перед их использованием

$numRecords->execute();

$numRecords->store_result();

вот и все

Надер Бен Мабрук
источник
1

Другая причина: store_result () нельзя вызвать дважды.

Например, в следующем коде печатается ошибка 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);

(Это может не иметь отношения к исходному образцу кода, но может иметь отношение к людям, ищущим ответы на эту ошибку.)

Дэвид Г.
источник
1

Вот в чем была МОЯ ПРОБЛЕМА !!!

Привязка параметров была "динамической", поэтому у меня была переменная, которая устанавливает параметры данных, чтобы использовать bind_param . Итак, эта переменная была неправильной, но вместо того, чтобы выдавать ошибку типа «неправильные данные параметров», она говорит «рассинхронизация бла бла бла», поэтому я был сбит с толку ...

Ари Вайсберг
источник
0

Я думаю, проблема в том, что вы устанавливаете новое соединение в функции, а затем не закрываете его в конце. Почему бы вам не попробовать передать существующее соединение и повторно использовать его?

Другая возможность заключается в том, что вы возвращаетесь из середины выборки цикла while. Вы никогда не завершите эту внешнюю выборку.

Пол Томблин
источник
1
Если я сделаю $ con глобальным (что является плохой практикой, но должно работать так, как вы описываете), у меня все равно будет та же ошибка.
1
Я не думаю, что иметь глобальную связь - плохая практика
Мэтью Дж
0

Проверьте, правильно ли вы вводите все параметры. Он выдает ту же ошибку, если количество параметров, определенных и затем переданных в функцию, отличается.

Mixtelf
источник
0

Это не связано с исходным вопросом, но у меня было такое же сообщение об ошибке, и этот поток является первым попаданием в Google, и мне потребовалось время, чтобы выяснить, в чем проблема, поэтому он может быть полезен для других:

Я НЕ использую mysqli, все еще использую mysql_connect. У меня было несколько простых запросов, но ОДИН запрос привел к сбою всех других запросов в том же соединении.

Я использую mysql 5.7 и php 5.6. У меня была таблица с типом данных «JSON». очевидно, что моя php-версия не распознала возвращаемое значение от mysql (php просто не знал, что делать с JSON-форматом, потому что встроенный mysql-модуль был слишком стар (по крайней мере, я думаю))

на данный момент я изменил JSON-Field-Type на Text (на данный момент мне не нужны встроенные функции mysql JSON), и все работает нормально

мех
источник
0

Если вы используете набор результатов с буферизацией или без буферизации для выборки данных, сначала вы должны просто очистить полученные данные из памяти, как только вы загрузите все данные . Поскольку вы не можете выполнить другую процедуру MYSQL в том же соединении, пока не очистите извлеченную память. Добавьте эту функцию ниже в правый конец вашего скрипта, чтобы она решила проблему

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

Ссылка из документации PHP

Каз
источник
1
Если вам не нужны какие-то записи, то вам вообще не следовало выбирать их. Вместо того, чтобы просто освободить их, просто не выбирайте их вообще. А если это не так, и вы извлекли все выбранные записи, то такой ошибки не будет, также нет необходимости вызывать close () или free (). Что касается хранимых процедур, существует менее варварский метод, описанный в ответах выше
Your Common Sense
0

Я столкнулся с этой ошибкой, используя Doctrine DBAL QueryBuilder.

Я создал запрос с помощью QueryBuilder, который использует подзапросы столбцов, также созданные с помощью QueryBuilder. Подзапросы были созданы только через, $queryBuilder->getSQL()а не выполнены. Ошибка при создании второго подзапроса. Предварительно выполняя каждый подзапрос с $queryBuilder->execute()помощью перед использованием $queryBuilder->getSQL(), все работало. Это как если бы соединение $queryBuilder->connectionостается в недопустимом состоянии для создания нового SQL перед выполнением текущего подготовленного SQL, несмотря на новый экземпляр QueryBuilder для каждого подзапроса.

Мое решение состояло в том, чтобы писать подзапросы без QueryBuilder.

Фабиан Пиконе
источник
0

Я использую ODBC, и это исправление у меня работает: ODBC -> вкладка Системный DSN -> дважды щелкните, чтобы настроить мой источник данных -> подробности -> вкладка Курсоры -> снимите флажок [Не кэшировать результаты курсоров только вперед] - > нажмите ОК

Teemo
источник
0

Я часто сталкиваюсь с этой ошибкой, и это всегда, когда я запускаю хранимую процедуру, которую я отлаживал в phpmyadmin или SQL Workbench (я работаю в php, соединяясь с mysqli).

Ошибка возникает из-за того, что отладка включает в себя вставку операторов SELECT в стратегические точки кода, чтобы сообщить мне состояние переменных и т. Д. Запуск хранимой процедуры, которая выдает несколько наборов результатов в этих клиентских средах, нормально, но она дает " Ошибка "рассинхронизации команд" при вызове из php. Решение всегда состоит в том, чтобы закомментировать или удалить отладочные выборки, чтобы процедура имела только один набор результатов.

Никкорян
источник
0

Просто для справки, у меня возникла проблема с смешиванием обоих multi_queryи queryв одном коде:

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

Который для того, что я читал, имел ожидающие неизрасходованные результаты, поэтому вызывало указанную ошибку.

Я решил это с помощью цикла, потребляющего все результаты multi_query:

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

В моем случае все запросы в multi_querywhere вставляются, поэтому сами результаты меня не интересовали.

Исак
источник
-1

Моя проблема заключалась в том, что я использовал сначала инструкцию подготовки, а затем я использовал запрос mysqli на той же странице и получал ошибку «Команды не синхронизированы; вы не можете запустить эту команду сейчас». Ошибка была только тогда, когда я использовал код с оператором подготовки.

Я закрыл вопрос. и это сработало.

mysqli_stmt_close ($ stmt);

Мой код

get_category.php (здесь используется инструкция подготовки)

    <?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 (здесь 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>

То, что только что пришло мне в голову, я снова добавляю переменную соединения через global $ connection ;. Итак, я думаю, что в основном новый набор системы запросов запускается после завершения оператора подготовки с mysqli_stmt_close ($ stmt); а также я добавляю эти файлы и другие вещи через include

Махад Али
источник
get_category.php (здесь используется инструкция prepare) pastebin.com/BiWysdYz admin_get_category_body.php (здесь mysqli) pastebin.com/Pwm30icm Примечание. Не могу опубликовать весь код из-за ограничений
Махад Али
То, что только что пришло мне в голову, я снова добавляю переменную соединения через global $ connection ;. Итак, я думаю, что в основном новый набор системы запросов запускается после завершения оператора подготовки с mysqli_stmt_close ($ stmt); а также я добавляю эти файлы и другие вещи через include.
Махад Али
-1

Это старый вопрос, но ни один из опубликованных ответов в моем случае не сработал, я обнаружил, что в моем случае у меня были выборки и обновления в таблице в моей хранимой процедуре, в той же таблице был триггер обновления, который запускался и отправлял процедура в бесконечный цикл. Как только ошибка была обнаружена, ошибка исчезла.

Shelbypereira
источник