Команди не синхронізовані; ви не можете запустити цю команду зараз


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, я все одно отримую команду з помилки синхронізації.

Відповіді:


115

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

Детальніше див. Тут .


3
Я згоден, mysqli трохи пошкоджений мозок. Однак він робить правильно з драйвером PDO mysql.

17
Ви можете мати два одночасних запити - вам просто потрібно запустити, $stmt->store_result();я думаю, ваша відповідь повинна зробити це більш чітким.
Тінь

3
Мені потрібно вік, щоб знайти цю інформацію - ніде її легко відобразити. Дякую. Я просто розділяю свої запити, $select_stmt->close();щоб розділити їх (не одночасно, а процедурно
n34_panda

@flussence, Ви заявили, що "mysqli за замовчуванням використовує буферизовані запити". То як ми можемо налаштувати це на інше?
Pacerier

1
Я знаю, що це здається дивним, але у мене виникла ця помилка під час виконання запиту, при якому mysqli_query порушує зовнішній ключ ... тому, якщо це трапляється з ким-небудь, перевірте, що ваш запит INSERT не порушує жодного зовнішнього ключа
lucaferrario

34

Я вирішив цю проблему у своєму додатку C - ось як я це зробив:

  1. Цитування з форумів MySQL:

    Ця помилка виникає, коли ви закінчуєте свій запит розділювачем із крапкою з комою всередині програми . Незважаючи на те, що при завершенні запиту з командного рядка або в браузері запитів потрібно завершити запит з розділювачем з комою, видаліть розділювач із запиту всередині вашої програми.

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

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

    Це цикл, який я використовую:

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

Я не знаю PHP, але впевнений, що в ньому є щось подібне.


11
Це було для мене. У PHP я щойно додав: while (mysqli_next_result ($ con));
Джош

Дякую за відповідь, яка вирішила мою проблему. Я видалив роздільник, і він працює. Я не звільнив (не отримав) і не зберіг свої результати, а закрив курсор і повторно побудував, як тільки закінчив один оператор запиту.
Chen Xie

@Josh, як це зробити у застарілому mysqlрозширенні?
Pacerier

1
Видалення крапки з комою в кінці запиту виправило проблему "Команди не синхронізовані; Ви не можете запустити цю команду зараз" під час використання Python MySQLdb.
Геном

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());        

}

5

Як тільки ви використовували

stmt->execute();

Ви МОЖЕТЕ закрити його, щоб використати інший запит.

stmt->close();

Ця проблема полювала на мене годинами. Сподіваємось, це виправить.


1
Закривати заяву не потрібно. Як @stalinbeltran відповів вище, нам потрібно "спожити" результат заяви перед тим, як готувати іншу. Отже, $stmt1->execute(); $stmt2=$conn->prepare(...)дав би цю помилку, але $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)працював би чудово.
Джей

Брат, це допомогло мені спасибі. f з усіх, хто говорить це і те, я використовував mysqli_prepare два рази, перш ніж закрити перший. Це працює.
Абхінаш Маджі

2

Я використовую CodeIgniter. Один сервер ОК ... цей, мабуть, старший ... У будь-якому випадку, використовуючи

$this->db->reconnect();

Виправлено.


7
Як це вирішує проблему?
Jeremy J Starcher

4
@ Норман, це не "вирішує" проблему. Це просто уникає цього, кидаючи весь зв’язок і знову підключаючись. Це зовсім не має сенсу з точки зору продуктивності.
Pacerier

1

Проблема полягає в бібліотеці клієнта C MySQL, на якій побудовано більшість API MySQL. Проблема полягає в тому, що бібліотека C не підтримує одночасне виконання запитів, тому всі API, побудовані поверх них, також не підтримують. Навіть якщо ви використовуєте буферизовані запити. Це одна з причин, чому був написаний асинхронний API MySQL. Він взаємодіє безпосередньо з сервером MySQL з використанням протоколу TCP і провід-протоколом робить підтримку одночасних запитів.

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


1
Мені не потрібно одночасно виконувати обидва, я радий, що countQuery повністю закінчується до мого другого запиту, але я не впевнений, як зупинити countQuery у виконанні

Ви не отримуєте жодних даних із countQuery, тому вони все ще "тривають". Або отримайте всі рядки, або змініть його на SELECT COUNT (ARTICLE_NO) і отримайте цей рядок. Тоді ваш другий запит буде запущений.
staticsan

Коли ви говорите "асинхронний API MySQL", до якого API ви маєте на увазі? Крім того, я не отримую вашого висновку. Цю "проблему" можна виправити, не вимагаючи асинхронності API.
Пейс'єр

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 . Отже, ця змінна була неправильною, але замість того, щоб видавати помилку, як "неправильні дані параметрів", там написано "не синхронізовано bla bla bla", тому я був розгублений ...


0

Я думаю, проблема полягає в тому, що ви встановлюєте нове з'єднання у функції, а потім не закриваєте його наприкінці. Чому б вам не спробувати передати існуюче з'єднання та не використати його повторно?

Інша можливість полягає в тому, що ви повертаєтеся із середини часу отримання циклу. Ви ніколи не виконуєте цей зовнішній вибір.


1
Якщо я роблю $ con глобальним (що є поганою практикою, але повинно працювати так, як ви описуєте), у мене все одно буде та сама помилка.

1
я не думаю, що глобальний зв’язок є поганою практикою
Матьє Дж

0

Перевірте, чи правильно ви вводите всі параметри. Він видає ту саму помилку, якщо кількість параметрів, визначених, а потім переданих функції, відрізняється.


0

Це не пов’язано з початковим запитанням, але у мене було те саме повідомлення про помилку, і цей потік є першим зверненням до Google, і мені знадобився час, щоб з’ясувати, в чому проблема, тому він може бути корисним для інших:

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

Я використовую mysql 5.7 і php 5.6, у мене була таблиця з типом даних "JSON". очевидно, моя php-версія не розпізнала повернене значення з mysql (php просто не знав, що робити з JSON-Format, оскільки вбудований модуль 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 (). Що стосується збережених процедур, існує менш варварський метод, описаний у відповідях вище
Ваш здоровий глузд

0

Я зіткнувся з цією помилкою, використовуючи Doctrine DBAL QueryBuilder.

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

Моїм рішенням було написати підвибори без QueryBuilder.


0

Я використовую ODBC, і це виправлення працює для мене: ODBC -> вкладка Системний DSN -> двічі клацніть для налаштування мого джерела даних -> деталі -> вкладка Курсори -> Зніміть прапорець [Не кешувати результати курсорів, що прямують лише вперед] - > натисніть кнопку Ok


0

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

Помилка виникає внаслідок того, що налагодження включає вставку операторів SELECT у стратегічні точки коду, щоб повідомити мені про стан змінних тощо. Запуск збереженої процедури, яка створює кілька наборів результатів у цих клієнтських середовищах, є нормальним, але вона видає " Команди не синхронізуються "помилка при виклику з php. Рішення завжди полягає у вилученні коментарів або видаленні вибраних налагоджувальних процесів, тому процедура має лише один набір результатів.


-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>

Щось, що мені щойно спало на думку, я також знову додаю змінну з'єднання через глобальне з'єднання $ ;. Тому я думаю, що в основному починається цілий новий набір системи запитів після закінчення оператора підготовки за допомогою mysqli_stmt_close ($ stmt); а також я додаю ці файли та інші речі через include


get_category.php (тут за допомогою оператора підготовки) pastebin.com/BiWysdYz admin_get_category_body.php (тут mysqli) pastebin.com/Pwm30icm Примітка: Не вдається опублікувати весь код через обмеження
Махад Алі,

Щось, що мені щойно спало на думку, я також знову додаю змінну з'єднання через глобальне з'єднання $ ;. Тому я думаю, що в основному починається цілий новий набір системи запитів після закінчення оператора підготовки за допомогою mysqli_stmt_close ($ stmt); а також я додаю ці файли та інші речі через include.
Махад Алі,

-1

Це старе запитання, але жодна з опублікованих відповідей не спрацювала в моєму випадку, я виявив, що в моєму випадку у мене були вибори та оновлення в таблиці в моїй збереженій процедурі, та ж таблиця мала тригер оновлення, який запускався і відсилав процедура у нескінченний цикл. Після виявлення помилки помилка зникла.


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.