Comandos fora de sincronia; você não pode executar este comando agora

94

Estou tentando executar meu código PHP, que chama duas consultas MySQL via mysqli, e recebo o erro "Comandos fora de sincronia; você não pode executar este comando agora".

Aqui está o código que estou usando

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

Tentei ler sobre isso, mas não tenho certeza do que fazer. Eu li sobre o resultado da loja e o resultado livre, no entanto, eles não fizeram diferença ao usá-los. Não sei exatamente em que ponto esse erro está sendo causado e gostaria de saber por que ele está sendo causado e como corrigi-lo.

Indo pelas minhas instruções de depuração, o primeiro loop if para countQuery nem mesmo está sendo inserido, por causa de um erro na minha sintaxe sql próximo '% ? %'. No entanto, se eu apenas selecionar em *vez de tentar limitar com base em uma cláusula LIKE, ainda recebo o erro de erro de sincronização do comando.

Joshxtothe4
fonte

Respostas:

115

Você não pode ter duas consultas simultâneas porque mysqli usa consultas sem buffer por padrão (para instruções preparadas; é o oposto para vanilla mysql_query). Você pode buscar o primeiro em um array e fazer um loop nele, ou dizer ao mysqli para armazenar as consultas (usando $stmt->store_result()).

Veja aqui os detalhes.

HoLyVieR
fonte
3
Eu concordo, mysqli tem um pouco de dano cerebral. Ele faz a coisa certa com o driver PDO mysql.
17
Você pode ter duas consultas simultâneas - você só precisa executar. $stmt->store_result();Acho que sua resposta deve deixar isso mais claro.
Shadow
3
Levo muito tempo para descobrir essas informações - em nenhum lugar elas são exibidas facilmente. Obrigado. Acabei de separar minhas consultas com $select_stmt->close();para dividi-las (não simultâneas, mas procedimentais
n34_panda
@flussence, Você afirmou que "mysqli usa consultas sem buffer por padrão". Então, como podemos configurá-lo para fazer o contrário?
Pacerier
1
Eu sei que parece estranho, mas eu tive este erro ao executar uma consulta com mysqli_query violando uma chave estrangeira ... então se isso acontecer com alguém, verifique se sua consulta INSERT não está violando nenhuma chave estrangeira
lucaferrario
33

Resolvi esse problema em meu aplicativo C - eis como fiz:

  1. Citando de fóruns do mysql:

    Este erro ocorre quando você encerra sua consulta com um delimitador de ponto-e-vírgula dentro do aplicativo . Embora seja necessário encerrar uma consulta com um delimitador de ponto-e-vírgula ao executá-la na linha de comando ou no navegador de consulta, remova o delimitador da consulta dentro de seu aplicativo.

  2. Depois de executar minha consulta e lidar com os resultados [C API: mysql_store_result()], eu itero sobre quaisquer outros resultados potencialmente pendentes que ocorram por meio da execução de várias instruções SQL, como duas ou mais instruções select (consecutivas sem lidar com os resultados).

    O fato é que meus procedimentos não retornam vários resultados, mas o banco de dados não sabe disso até que eu execute: [C API: mysql_next_result()]. Eu faço isso em um loop (para uma boa medida) até que ele retorne diferente de zero. É quando o manipulador de conexão atual sabe que está tudo bem para executar outra consulta (eu coloco meus manipuladores em cache para minimizar a sobrecarga de conexão).

    Este é o loop que uso:

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

Não conheço PHP, mas tenho certeza de que tem algo semelhante.

tracy.brown
fonte
11
Isso foi tudo para mim. No PHP, acabei de adicionar: while (mysqli_next_result ($ con));
Josh
Obrigado pela resposta que resolveu meu problema. Removi o delimitador e funciona. Não liberei (busque) ou armazenei meus resultados, mas fechei o cursor e recompilei uma vez que terminei uma instrução de consulta.
Chen Xie
@Josh, como fazer isso na mysqlextensão legada ?
Pacerier de
1
A remoção do ponto-e-vírgula no final da consulta corrigiu o problema "Comandos fora de sincronia; você não pode executar este comando agora" ao usar o MySQLdb do Python.
Genoma de
17

Tive hoje o mesmo problema, mas apenas ao trabalhar com um procedimento armazenado. Isso faz com que a consulta se comporte como uma consulta múltipla, então você precisa "consumir" outros resultados disponíveis antes de fazer outra consulta.

while($this->mysql->more_results()){
    $this->mysql->next_result();
    $this->mysql->use_result();
}
stalin beltran
fonte
Este é um ponto significativo: os procedimentos armazenados retornam um conjunto de resultados além de qualquer conjunto de resultados que o código no SP possa gerar. Você precisa lidar com isso ou obterá este erro: stackoverflow.com/a/2315229/4495850
Richard
11

Eu chamo esta função todas as vezes antes de usar $ mysqli-> query. Funciona com stored procedures também.

function clearStoredResults(){
    global $mysqli;

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

}
Juergen
fonte
5

Uma vez que você usou

stmt->execute();

Você PODE fechá-lo para usar outra consulta.

stmt->close();

Este problema estava me perseguindo por horas. Esperançosamente, ele consertará o seu.

Carl James
fonte
1
Fechar o extrato não é necessário. Como @stalinbeltran respondeu acima, precisamos "consumir" o resultado de uma declaração antes de preparar outra. Então, $stmt1->execute(); $stmt2=$conn->prepare(...)daria esse erro, mas $stmt1->execute(); $result1=$stmt1->get_result(); $stmt2=$conn->prepare(...)funcionaria bem.
Jay Dadhania
Mano me ajudou muito obrigado. Para todos que falam isso e aquilo, usei mysqli_prepare duas vezes antes de fechar a primeira. Funciona.
Abhinash Majhi
2

Eu uso o CodeIgniter. Um servidor OK ... este provavelmente mais antigo ... De qualquer forma, usando

$this->db->reconnect();

Corrigido.

normando
fonte
7
Como isso resolve o problema?
Jeremy J Starcher
4
@ Norman, isso não "corrige" o problema. Ele simplesmente o evita , jogando fora toda a conexão e reconectando novamente. Isso não faz sentido do ponto de vista de desempenho.
Pacerier
1

O problema é a biblioteca C do cliente MySQL, na qual a maioria das APIs do MySQL é construída. O problema é que a biblioteca C não suporta a execução simultânea de consultas, então todas as APIs construídas sobre ela também não suportam. Mesmo se você usar consultas sem buffer. Este é um dos motivos pelos quais a API MySQL assíncrona foi escrita. Ele se comunica diretamente com o servidor MySQL usando TCP e o protocolo com fio oferece suporte a consultas simultâneas.

Sua solução é modificar o algoritmo para que você não precise ter ambos em andamento ao mesmo tempo, ou alterá-los para usar consultas em buffer, o que é provavelmente uma das razões originais para sua existência na biblioteca C (o outro é fornecer uma espécie de cursor).

staticsan
fonte
1
Eu não preciso ter ambos em andamento ao mesmo tempo, fico feliz que countQuery termine completamente antes da minha segunda consulta, mas não tenho certeza de como impedir que countQuery esteja em progresso
Você não está recuperando nenhum dado de countQuery, é por isso que ainda está 'em andamento'. Recupere todas as linhas ou altere-o para SELECT COUNT (ARTICLE_NO) e obtenha essa linha. Em seguida, sua segunda consulta será executada.
staticsan
Quando você diz "a API MySQL assíncrona", a qual API você está se referindo? Além disso, não estou obtendo sua conclusão. Esse "problema" pode ser corrigido sem a necessidade de a API ser assíncrona.
Pacerier
1
Para ser honesto, @Pacerier, também não tenho mais certeza do que quis dizer! Muita coisa aconteceu em seis anos com a conectividade MySQL, então tudo o que eu pensei que estava me referindo provavelmente foi renomeado e / ou incorporado em algum outro driver novo.
staticsan
1

para resolver este problema, você deve armazenar os dados do resultado antes de usá-lo

$numRecords->execute();

$numRecords->store_result();

Isso é tudo

Nader Ben Mabrouk
fonte
1

Outra causa: store_result () não pode ser chamado duas vezes.

Por exemplo, no código a seguir, Erro 5 é impresso.

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

(Isso pode não ser relevante para o código de amostra original, mas pode ser relevante para pessoas que buscam respostas para esse erro.)

David G.
fonte
1

Aqui está o que era MEU PROBLEMA !!!

A ligação do parâmetro era "dinâmica", então eu tinha uma variável que define os parâmetros dos dados para usar bind_param . Então essa variável estava errada, mas em vez de lançar um erro como "dados de parâmetro errados", ela diz "fora de sincronia, bla bla bla", então fiquei confuso ...

Ari Waisberg
fonte
0

Acho que o problema é que você está fazendo uma nova conexão na função e depois não fecha no final. Por que você não tenta passar a conexão existente e reutilizá-la?

Outra possibilidade é que você esteja retornando no meio de uma busca por loop while. Você nunca completa aquela busca externa.

Paul Tomblin
fonte
1
Se eu tornar $ con global (o que é uma má prática, mas deve funcionar como você descreveu), continuarei com o mesmo erro.
1
Eu não acho que ter uma conexão global é uma prática ruim
Mathieu J.
0

Verifique se você está digitando todos os parâmetros corretamente. Ele gera o mesmo erro se a quantidade de parâmetros definidos e depois passados ​​para a função forem diferentes.

Mixtelf
fonte
0

Isso não está relacionado à pergunta original, mas recebi a mesma mensagem de erro e este tópico é o primeiro hit no Google e demorei um pouco para descobrir qual era o problema, então pode ser útil para outros:

NÃO estou usando o mysqli, ainda estou usando o mysql_connect. Tive algumas querys simples, mas UMA consulta fez com que todas as outras querys falhassem na mesma conexão.

Eu uso o mysql 5.7 e php 5.6 eu tinha uma tabela com o tipo de dados "JSON". obviamente, minha versão php não reconheceu o valor de retorno do mysql (php simplesmente não sabia o que fazer com o formato JSON porque o módulo interno do mysql era muito antigo (pelo menos eu acho))

por enquanto eu mudei o JSON-Field-Type para Text (por enquanto eu não preciso da funcionalidade JSON nativa do mysql) e tudo funciona bem

mech
fonte
0

Se você usar o conjunto de resultados Buffered ou Unbuffered para buscar dados, primeiro você deve simplesmente limpar os dados buscados da memória, uma vez que tenha buscado todos os dados . Como você não pode executar outro procedimento MYSQL na mesma conexão até limpar a memória buscada. Adicione esta função abaixo à direita do seu script, então ela resolverá o problema

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

Referência da documentação do PHP

Kaz
fonte
1
Se você não precisa de alguns registros, então não deveria tê-los selecionado em primeiro lugar. Em vez de apenas libertá-los, simplesmente não os selecione. E se não for o caso e você buscou todos os registros selecionados, então não haverá tal erro também, não há necessidade de chamar close () ou free (). Quanto aos procedimentos armazenados, há um método menos bárbaro, descrito nas respostas acima
Seu senso comum
0

Eu encontrei este erro usando Doctrine DBAL QueryBuilder.

Criei uma consulta com QueryBuilder que usa subseleções de coluna, também criada com QueryBuilder. As subseleções só foram criadas via $queryBuilder->getSQL()e não executadas. O erro aconteceu ao criar a segunda subseleção. Ao executar provisoriamente cada subseleção $queryBuilder->execute()antes de usar $queryBuilder->getSQL(), tudo funcionou. É como se a conexão $queryBuilder->connectionpermanecesse em um estado inválido para a criação de um novo SQL antes de executar o SQL atualmente preparado, apesar da nova instância QueryBuilder em cada subseleção.

Minha solução foi escrever as subseleções sem QueryBuilder.

Fabian Picone
fonte
0

Estou usando ODBC, e essa correção funciona para mim: ODBC -> guia System DSN -> clique duas vezes para configurar minha fonte de dados -> detalhes -> guia Cursores -> Desmarque [Não armazenar em cache os resultados de cursores somente de encaminhamento] - > clique em Ok

Teemo
fonte
0

Freqüentemente, encontro esse erro e é sempre que executo um procedimento armazenado que dependo no phpmyadmin ou no SQL Workbench (estou trabalhando em php conectando-se ao mysqli).

O erro resulta do fato de que a depuração envolve a inserção de instruções SELECT em pontos estratégicos no código para me dizer o estado das variáveis, etc. Executar um procedimento armazenado que produz vários conjuntos de resultados nesses ambientes de cliente é bom, mas produz o " Erro de comandos fora de sincronia "quando chamado de php. A solução é sempre comentar ou remover as seleções de depuração para que o procedimento tenha apenas um conjunto de resultados.

Nikkorian
fonte
-1

Meu problema era que eu estava usando primeiro a instrução prepare e, em seguida, estava usando a consulta mysqli na mesma página e estava recebendo o erro "Comandos fora de sincronia; você não pode executar este comando agora". O erro foi só então quando eu estava usando o código que tinha o comando prepare.

O que fiz foi encerrar a pergunta. e funcionou.

mysqli_stmt_close ($ stmt);

Meu código

get_category.php (aqui usando a instrução prepare)

    <?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 (aqui 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>

Algo que acabou de passar pela minha cabeça, também estou adicionando novamente a variável de conexão via $ connection global ;. Então, acho que basicamente um novo conjunto de sistema de consulta está sendo iniciado após o término da instrução prepare com mysqli_stmt_close ($ stmt); e também estou adicionando esses arquivos e outras coisas via include

Mahad Ali
fonte
get_category.php (aqui usando a instrução prepare) pastebin.com/BiWysdYz admin_get_category_body.php (aqui mysqli) pastebin.com/Pwm30icm Nota: Não é possível postar todo o código devido à limitação
Mahad Ali
Algo que acabou de passar pela minha cabeça, também estou adicionando novamente a variável de conexão via $ connection global ;. Então, acho que basicamente um novo conjunto de sistema de consulta está sendo iniciado após o término da instrução prepare com mysqli_stmt_close ($ stmt); e também estou adicionando esses arquivos e outras coisas via include.
Mahad Ali
-1

Esta é uma pergunta antiga, mas nenhuma das respostas postadas funcionou no meu caso, eu descobri que no meu caso eu tinha seleções e atualizações em uma tabela no meu procedimento armazenado, a mesma tabela tinha um gatilho de atualização que estava sendo disparado e acionando o procedimento em um loop infinito. Assim que o bug foi encontrado, o erro foi embora.

Shelbypereira
fonte