web-dev-qa-db-ja.com

Laravel:一般的なエラー:1615準備済みステートメントを再準備する必要があります

ホームステッド仮想マシン(贅沢)でlaravel(5.1)の最新バージョンを使用しています。

プロジェクトをローカルmariaDBサーバーに接続します。このサーバーには、いくつかのテーブルと2つのdb-viewがあります。

Db-viewテーブルのみを選択したため、このエラーがランダムに返されます。

一般的なエラー:1615準備済みステートメントを再準備する必要があります

今日から、dbビューでのみ選択すると、常にこのエラーが発生します。 phpMyAdminを開いて同じ選択をすると、正しい結果が返されます。

php artisan tinkerを開いてdb-viewのレコードを1つ選択しようとしましたが、同じエラーが返されました。

// Select one user from user table
>>> $user = new App\User
=> <App\User #000000006dc32a890000000129f667d2> {}
>>> $user = App\User::find(1);
=> <App\User #000000006dc32a9e0000000129f667d2> {
       id: 1,
       name: "Luca",
       email: "[email protected]",
       customerId: 1,
       created_at: "2015-08-06 04:17:57",
       updated_at: "2015-08-11 12:39:01"
   }
>>> 
// Select one source from Source db-view
>>> $source = new App\Source
=> <App\Source #000000006dc32a820000000129f667d2> {}
>>> $source = App\Source::find(1);
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from `sources` where `sources`.`id` = 1 limit 1)'

どうすれば修正できますか? mysqldumpの問題(私の場合はそうではありません)を読み、table_definition_cacheの値を増やします。

これはlaravelバグの一種ですか?

どうすればそれを理解できますか?


編集:

尋ねられたように、モデルのソースコードを追加します。 Source.php:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Source extends Model
{
    protected $table = 'sources';


    /*
    |--------------------------------------------------------------------------
    | FOREIGN KEYS
    |--------------------------------------------------------------------------
    */

    /**
     * 
     * @return [type] [description]
     */
    public function customersList(){
        return $this->hasMany("App\CustomerSource", "sourceId", "id");
    }


    /**
     * 
     * @return [type] [description]
     */
    public function issues(){
        return $this->hasMany("App\Issue", "sourceId", "id");
    }
}

編集2:

Mysqliを使用してプロジェクトで同じクエリを実行すると、機能します。

$db = new mysqli(getenv('DB_Host'), getenv('DB_USERNAME'), getenv('DB_PASSWORD'), getenv('DB_DATABASE'));
if($db->connect_errno > 0){
    dd('Unable to connect to database [' . $db->connect_error . ']');
}
$sql = "SELECT * FROM `sources` WHERE `id` = 4";
if(!$result = $db->query($sql)){
    dd('There was an error running the query [' . $db->error . ']');
}

dd($result->fetch_assoc());

編集3:アフェター2ヶ月、私はまだそこにいます。同じエラーがあり、解決策は見つかりませんでした。私はaritsanティンカーで少し解決策を試すことにしましたが、良いニュースはありません。私が試したことを報告します:

まず、テーブルモデルをフェッチしてみます。

>>> $user = \App\User::find(1);
=> App\User {#697
     id: 1,
     name: "Luca",
     email: "[email protected]",
     customerId: 1,
     created_at: "2015-08-06 04:17:57",
     updated_at: "2015-10-27 11:28:14",
   }

次に、ビューテーブルモデルをフェッチしてみます。

>>> $ir = \App\ContentRepository::find(15);
Illuminate\Database\QueryException with message 'SQLSTATE[42S02]: Base table or view not found: 1146 Table 'dbname.content_repositories' doesn't exist (SQL: select * from `content_repositories` where `content_repositories`.`id` = 1 limit 1)'

ContentRepositoryのモデルContentRepository.php内に正しいテーブル名が設定されていない場合:

>>> $pdo = DB::connection()->getPdo();
=> PDO {#690
     inTransaction: false,
     errorInfo: [
       "00000",
       1146,
       "Table 'dbname.content_repositories' doesn't exist",
     ],
     attributes: [
       "CASE" => NATURAL,
       "ERRMODE" => EXCEPTION,
       "AUTOCOMMIT" => 1,
       "PERSISTENT" => false,
       "DRIVER_NAME" => "mysql",
       "SERVER_INFO" => "Uptime: 2513397  Threads: 12  Questions: 85115742  Slow queries: 6893568  Opens: 1596  Flush tables: 1  Open tables: 936  Queries per second avg: 33.864",
       "Oracle_NULLS" => NATURAL,
       "CLIENT_VERSION" => "mysqlnd 5.0.11-dev - 20120503 - $Id: id_here $",
       "SERVER_VERSION" => "5.5.5-10.0.17-MariaDB-1~wheezy-wsrep-log",
       "STATEMENT_CLASS" => [
         "PDOStatement",
       ],
       "EMULATE_PREPARES" => 0,
       "CONNECTION_STATUS" => "localiphere via TCP/IP",
       "DEFAULT_FETCH_MODE" => BOTH,
     ],
   }
>>> 

モデルContentRepository.php内のテーブル値を変更します。

>>> $ir = \App\ContentRepository::find(15);
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from `contentRepository` where `contentRepository`.`id` = 15 limit 1)'

正しければ、欠落している「errorInfo」に注意

>>> $pdo = DB::connection()->getPdo();
=> PDO {#690
     inTransaction: false,
     attributes: [
       "CASE" => NATURAL,
       "ERRMODE" => EXCEPTION,
       "AUTOCOMMIT" => 1,
       "PERSISTENT" => false,
       "DRIVER_NAME" => "mysql",
       "SERVER_INFO" => "Uptime: 2589441  Threads: 13  Questions: 89348013  Slow queries: 7258017  Opens: 1604  Flush tables: 1  Open tables: 943  Queries per second avg: 34.504",
       "Oracle_NULLS" => NATURAL,
       "CLIENT_VERSION" => "mysqlnd 5.0.11-dev - 20120503 - $Id: id_here $",
       "SERVER_VERSION" => "5.5.5-10.0.17-MariaDB-1~wheezy-wsrep-log",
       "STATEMENT_CLASS" => [
         "PDOStatement",
       ],
       "EMULATE_PREPARES" => 0,
       "CONNECTION_STATUS" => "localIPhere via TCP/IP",
       "DEFAULT_FETCH_MODE" => BOTH,
     ],
   }

データベースのテーブルを表示:

>>> $tables = DB::select('SHOW TABLES');
=> [
     {#702
       +"Tables_in_dbname": "table_name_there",
     },
     {#683
       +"Tables_in_dbname": "table_name_there",
     },
     {#699
       +"Tables_in_dbname": "table_name_there",
     },
     {#701
       +"Tables_in_dbname": "table_name_there-20150917-1159",
     },
     {#704
       +"Tables_in_dbname": "contentRepository", */ VIEW TABLE IS THERE!!!! /*
     },
     {#707
       +"Tables_in_dbname": "table_name_there",
     },
     {#684
       +"Tables_in_dbname": "table_name_there",
     },
   ]

通常の選択で試してください:

>>> $results = DB::select('select * from dbname.contentRepository limit 1');
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from dbname.contentRepository limit 1)'

準備されていないクエリを試してください:

>>> DB::unprepared('select * from dbname.contentRepository limit 1')
=> false

準備されていないクエリをもう一度試します:

>>> DB::unprepared('select * from dbname.contentRepository limit 1')
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active.  Consider using PDOStatement::fetchAll().  Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. (SQL: select * from dbname.contentRepository limit 1)'

PDOStatement :: fetchAll()を試してください:

>>> DB::fetchAll('select * from dbname.contentRepository limit 1'); 
PHP warning:  call_user_func_array() expects parameter 1 to be a valid callback, class 'Illuminate\Database\MySqlConnection' does not have a method 'fetchAll' in /Users/luca/company/Laravel/dbname/vendor/laravel/framework/src/Illuminate/Database/DatabaseManager.php on line 296

2番目のPDOStatement :: fetchAll()を試してください:

>>> $pdo::fetchAll('select * from dbname.contentRepository limit 1');
  [Symfony\Component\Debug\Exception\FatalErrorException]  
  Call to undefined method PDO::fetchAll()           

ステートメントを試してください...:

>>> $pdos = DB::statement('select * from dbname.contentRepository limit 1')
Illuminate\Database\QueryException with message 'SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared (SQL: select * from dbname.contentRepository limit 1)'

ありがとうございました

16
Tenaciousd93

追加して動作するようです

'options'   => [
                \PDO::ATTR_EMULATE_PREPARES => true
            ]

内側projectName/config/database.php DB構成のファイル。それは次のようになります:

'mysql' => [
    'driver'    => 'mysql',
    'Host'      => env('DB_Host', 'localhost'),
    'database'  => env('DB_DATABASE', 'forge'),
    'username'  => env('DB_USERNAME', 'forge'),
    'password'  => env('DB_PASSWORD', ''),
    'charset'   => 'utf8',
    'collation' => 'utf8_unicode_ci',
    'prefix'    => '',
    'strict'    => false,
    'options'   => [
        \PDO::ATTR_EMULATE_PREPARES => true
    ]
],

Laravel 5.1。お役に立てれば幸いです。

40
Tenaciousd93

受け入れられた回答のコメントに従って、実行

SET GLOBAL table_definition_cache = 1024

mariaDBで問題を解決しました。

https://mariadb.com/kb/en/library/server-system-variables/#table_definition_cache

7
TimoSolo

文書化された MySQL Bug のようです。

編集:

モデルは「id」を主キーとして使用していますか?私はそれがそうであってもモデルで主キーを明示的に設定したいです。

_protected $primaryKey = 'id'; // If different than id, definitely need to set the column here_

hasMany()関数をコメント化して再試行することもできます。 Laravelは、特にそれがマップしようとしているレコードがたくさんある場合、eagerLoadで奇妙なことをすることがあります。

0
Blake