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