Php 如何摆脱MySQL错误';准备好的报表需要重新准备';

Php 如何摆脱MySQL错误';准备好的报表需要重新准备';,php,mysql,Php,Mysql,我已经重写了我的网站php代码,并添加了MySQL存储过程 在我的本地版本中,一切正常,但在我将我的网站上传到托管服务器后,我不断收到致命错误“准备好的语句需要重新准备” 有时页面加载,有时加载失败,我看到这个错误。那是什么?这是一种可能性: 他们建议提高价格 您可以阅读有关重新准备的内容。我的解决方案是创建如下例程: DELIMITER $$ -- -- Procedimientos -- DROP PROCEDURE IF EXISTS `dch_content_class_content`

我已经重写了我的网站php代码,并添加了MySQL存储过程

在我的本地版本中,一切正常,但在我将我的网站上传到托管服务器后,我不断收到致命错误“准备好的语句需要重新准备”

有时页面加载,有时加载失败,我看到这个错误。那是什么?

这是一种可能性:

他们建议提高价格


您可以阅读有关重新准备的内容。

我的解决方案是创建如下例程:

DELIMITER $$
--
-- Procedimientos
--
DROP PROCEDURE IF EXISTS `dch_content_class_content`$$

CREATE DEFINER=`renuecod`@`localhost` PROCEDURE `dch_content_class_content`(IN $classId INTEGER)
BEGIN
-- vw_content_class_contents is a VIEW (UNIONS)
  select * from vw_content_class_contents;
END$$
public function scopeMyTable(Builder $query)
{
    return $query->join($this->myView(),'my_view_name.id','=','some_table.id');
}

我希望这能帮助一些人

我在共享托管环境中的RubyonRails中遇到了同样的错误。这可能不是最安全的解决方案,但禁用准备好的语句可以为我消除错误消息

这可以通过向database.yml文件添加“prepared_statements:false”设置来实现:

production:
  prepared_statements: false
当您无法控制MySQL服务器上的配置设置时,这似乎是一个合理的解决方案。

答案似乎不错,但在共享托管服务器上,并非所有人都允许触摸
表\u打开\u缓存
表\u定义\u缓存
选项

由于此错误与准备好的语句有关,因此我尝试通过提供以下选项来“模拟”使用PDO的语句:

$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, [
    PDO::ATTR_EMULATE_PREPARES => true
]);
注意:实际上这是在Laravel5.6项目中,我在
config/database.php
中添加了选项:

'connections' => [
    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => true,
        'engine' => null,
        'options' => [
            PDO::ATTR_EMULATE_PREPARES => true,
        ],
    ],
    (...)
],
我还没有测试模拟准备好的语句对加载我的站点的持续时间的影响,但是它可以对抗错误
SQLSTATE[HY000]:一般错误:1615准备好的语句需要重新准备


更新性能:模拟版本似乎稍快(模拟32.7±1.4ms,正常35.0±2.3ms,双尾学生T检验n=10,p值=0.027)。

问题:“准备好的陈述需要重新准备”

此问题通常发生在使用任何计算机语言(如Java)或从后端调用过程时

解决方案:通过使用(执行)下面的脚本来增加缓存的大小


脚本:设置全局表定义缓存=4000

这是一个解决方案,适用于那些使用共享主机并且不想冒险使用sql注入的人。根据这篇文章: 您可以将视图的定义存储在函数中

private function myView(){
    return DB::raw('(**definition of the view**) my_view_name)');
}
然后像这样使用它:

DELIMITER $$
--
-- Procedimientos
--
DROP PROCEDURE IF EXISTS `dch_content_class_content`$$

CREATE DEFINER=`renuecod`@`localhost` PROCEDURE `dch_content_class_content`(IN $classId INTEGER)
BEGIN
-- vw_content_class_contents is a VIEW (UNIONS)
  select * from vw_content_class_contents;
END$$
public function scopeMyTable(Builder $query)
{
    return $query->join($this->myView(),'my_view_name.id','=','some_table.id');
}

这是一种laravel方法,但我确信它可以应用于大多数情况,并且不需要大量的代码重构或架构更改。另外,它相对安全,因为您的语句保持准备状态。

简而言之:不要在准备好的语句中使用视图。

这似乎是一个持续的问题

使用动态SQL处理视图很麻烦

最早的错误是

另一个bug报告指出,当底层表忙时,错误1615不是bug。(真的吗?)

虽然增加表缓存大小有一些好处(请参阅)

替代品 一年多前,有人在报纸上提到了这一点

有人想出了一个好主意。另一个想法是


这些似乎是提高表缓存大小的更好的解决方法。

刷新表;comand在为我解决的数据库中,我使用的是doctrine orm。

首先访问mysql
shell:

mysql 
检查表\u定义\u缓存的值:

show global variables like '%table_definition_cache%';
可能是400或1400

放大它:

set global table_definition_cache = 4000;

很好

你为什么需要那种粗体和大字体?对不起,字体样式不是必需的。我希望我的贡献对某些人有用。下面的答案没有触及问题的核心。中有更多答案。您的评论不再正确。这些年来,我得到了更多的答案,现在下面的答案似乎给副本增加了很多内容(这确实没有什么帮助),我也面临着这个问题,这个解决方案很好。但出于安全原因,不建议这样做。但是,如果您愿意冒险或者别无选择,那么就这样吧:DSo到目前为止,我对准备好的本机与PDO相关的安全问题的搜索不会产生任何差异。这也是一个很好的起点。你为什么要考虑仿真风险?我承认我对这方面的知识有限,只是依赖于我刚刚发现的一些短信息。我一直认为增加
表\u定义\u缓存
是这里最合适的解决方案。但当我读到你的链接时,我开始怀疑了。事实上,我仍然面临这个问题,我注意到这发生在服务器PHP7.0上,而不是PHP5.6上(这在我的设置中是特定的)您在哪里运行上述脚本?如何提高表定义缓存的值?当我在我的
/etc/my.cnf
文件(在
[mysqld]
部分下)中添加
table\u definition\u cache=5000
并重新启动
mysqld
时,错误消失了。请注意,
my.cnf
可能位于不同的位置。这似乎也是MariaDB 10.0、10.1、10.2、10.3、10.4、10.1.34中的一个等效错误:具有类似的解决方法(将
table_definition_cache
增加到大于或等于
table_open_cache
)。实际上,我认为这是正确的答案,因为它指出了错误的原因,而不仅仅是通过更改服务器配置来处理影响!非常感谢-我将根据您的建议和链接的资源更改我的代码,希望这将最终解决这个奇怪的错误!这是一个非常糟糕的答案。在视图中使用准备好的语句对MySQL/MariaDB数据库是有效的。(我从在数百万个DB表中处理TB数据的经验中了解到,其中大多数都有视图)。更好的解决方案是为表\u xxx\u缓存确定适当的值(您的环境允许)或将SQL并发性限制在限制范围内。@JJorgenson您没有指定“适当的值”的含义。如何散热