如何摆脱MySQL错误'准备好的声明需要重新准备'

Rom*_*man 10 php mysql

我重写了我的网站php-code并添加了MySQL存储过程.

在我的本地版本一切正常,但在我将我的网站上传到托管服务器后,我一直在致命的错误'准备好的声明需要重新准备'.

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

更新: 移动到VPS服务器后问题已经消失.感谢帮助.

doc*_*hat 21

这是一种可能性:MySQL bug#42041

他们建议提高价值table_definition_cache.

您可以阅读MySQL文档中的重新准备.

  • 你如何提高 table_definition_cache 的值? (4认同)
  • 当我在“/etc/my.cnf”文件(在“[mysqld]”部分下)添加“table_definition_cache=5000”并重新启动“mysqld”时,错误消失了。请注意,“my.cnf”对于您来说可能位于不同的位置。 (3认同)
  • 在 MariaDB 10.0、10.1、10.2、10.3、10.4、10.1.34 中似乎也是一个等效的错误:https://jira.mariadb.org/browse/MDEV-17124,具有类似的解决方法(将 `table_definition_cache` 增加到大于或等于“table_open_cache”)。 (2认同)

Mar*_*ier 9

@ docwhat的答案似乎很好,但在共享托管服务器上,并不是每个人都可以触摸table_open_cachetable_definition_cache选项.

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

$dbh = new PDO('mysql:host=localhost;dbname=test', $user, $pass, [
    PDO::ATTR_EMULATE_PREPARES => true
]);
Run Code Online (Sandbox Code Playgroud)

注意:实际上这是在Laravel 5.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,
        ],
    ],
    (...)
],
Run Code Online (Sandbox Code Playgroud)

我没有测试模拟预准备语句对加载我的网站的持续时间的影响,但它对SQLSTATE[HY000]: General error: 1615 Prepared statement needs to be re-prepared我得到的错误有效.

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


Tur*_*gar 8

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

这似乎是一个持续存在的问题

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

最早的错误是11 年前无法在准备好的语句中创建视图。有一个补丁来解决它。

另一个错误报告Prepared-Statement failed when MySQL-Server under load指出,当底层表繁忙时,错误 1615 不是错误。(真的 ?)

虽然增加表缓存大小有一些优点(使用 mysql 视图时请参阅MySql 错误),但它并不总是有效(请参阅一般错误:1615 Prepared statement need to be re-prepared (selecting mysql view)

ALTERNATIVES 一年多以前,有人在MySQL 论坛中提到过这个(MySql“视图”、“准备好的语句”和“准备好的语句需要重新准备”)

有人想出了一个简单的想法,即不在准备好的语句中使用视图,而是在子查询中使用视图的 SQL。另一个想法是创建视图使用的 SQL 并在您的客户端代码中执行它

这些似乎是更好的解决方法,只是增加了表缓存大小。

  • 实际上我认为这是正确的答案,因为它指出了错误的原因,而不仅仅是通过更改服务器配置来处理效果!非常感谢 - 我将根据您的建议和链接资源更改我的代码,并希望这最终能解决这个奇怪的错误! (3认同)

小智 8

首先获得mysqlshell的访问权限:

mysql 
Run Code Online (Sandbox Code Playgroud)

检查table_definition_cache的值:

show global variables like '%table_definition_cache%';
Run Code Online (Sandbox Code Playgroud)

可能是400或1400。

放大看:

set global table_definition_cache = 4000;
Run Code Online (Sandbox Code Playgroud)

很高兴出发!


小智 5

问题:“准备好的语句需要重新准备”

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

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

脚本:设置全局 table_definition_cache = 4000;

  • 你到底在哪里运行上面的脚本? (3认同)

Fra*_*ank 5

就这样做:

\n
SET GLOBAL table_definition_cache = 4096;\nSET GLOBAL table_open_cache = 4096;\n
Run Code Online (Sandbox Code Playgroud)\n

4096 可能太小,所以将其设置为更高的值。但请确保两个值 \xe2\x80\x8b\xe2\x80\x8bar 相同。

\n