MySql“视图”、“准备好的语句”和“准备好的语句需要重新准备”

Posted

技术标签:

【中文标题】MySql“视图”、“准备好的语句”和“准备好的语句需要重新准备”【英文标题】:MySql "view", "prepared statement" and "Prepared statement needs to be re-prepared" 【发布时间】:2015-04-06 22:46:11 【问题描述】:

mysql 有问题,详情如下: 我创建了一个新的架构/数据库,(仅)执行了这个查询:

create table mytable (
id varchar(50) not null,
name varchar(50) null default '',
primary key (id));

create view myview as
select id,name from mytable;

insert into mytable values ('1','aaa');
insert into mytable values ('2','bbb');
insert into mytable values ('3','ccc');

然后,如果我运行这些查询:

select * from mytable;
select * from myview;
prepare cmd from 'select id,name from mytable where id=?';
set @param1 = '2';
execute cmd using @param1;

查询给出正确的结果(3 行、3 行、1 行)。

但是,如果我运行这个查询,问题就存在:

prepare cmd from 'select id,name from myview where id=?';
set @param1 = '2';
execute cmd using @param1;

错误:#1615 - 准备好的语句需要重新准备

我做了一些研究,发现下面的配置增量“可能”解决了这个问题:

increase table_open_cache_instances value
increase table_open_cache value
increase table_definition_cache value

据我所知,上面的查询都是常见的标准的MySql查询,所以我认为语法没有问题。

我在共享虚拟主机上,使用 MySql 版本是 5.6.22

但让我感到困惑的是,它只包含 1 个模式/数据库,1 个表,3 个短记录和 1 个视图, 我执行了一个通用和标准的 MySql 选择查询, 上面的值的增量真的需要吗? 有没有遇到同样问题的人增加了值并真正解决了问题? 或者,也许您有任何其他您认为可能或将有助于解决此问题的解决方案?

ps:它不会在一天中发生一次或两次(假设是由某些备份或相关原因引起的),而是整天(24 小时)。

谢谢。

【问题讨论】:

刚刚在 5.6.23 中测试过:不可重现...... 您是在mysql 客户端还是在php 代码内部进行操作? 我正在使用 PHPMyAdmin,如果我使用自定义 PHP 代码使用 mysqli 接口(准备语句命令),问题也会存在。 【参考方案1】:

每次执行后你都会这样做吗?

deallocate prepare cmd;

【讨论】:

我可以为自己说“是”.. 但它是一个共享虚拟主机,其他共享成员的操作是否对我也有影响? show status like 'com_stmt%'; Com_stmt_prepare 0 Com_stmt_reprepare 0 Com_stmt_close 0 Com_stmt_reset 0 Com_stmt_execute 0 Com_stmt_fetch 0 Com_stmt_send_long_data 0 show global status like 'com_stmt%'; Com_stmt_prepare 21538 Com_stmt_reprepare 222 Com_stmt_close 21194 Com_stmt_reset 11836 Com_stmt_fetch 0 Com_stmt_execute 21529 ...对于所有MySql DbAdmin专家,值好吗? 还有Com_dealloc_sql?在同一个存储过程调用中,必须(最终)在准备之后进行解除分配。 (我认为) 我也同意 prepare 后面必须跟 dellocate。我可以保证这不是我这边的问题,至少。 show status like 'com_deal%'; Com_dealloc_sql 0 show global status like 'com_deal%'; Com_dealloc_sql 236 ...您如何看待这些值?【参考方案2】:

到目前为止,最接近的猜测是服务器上的其他一些共享成员没有很好地编写他们的代码(因为它是一个共享的虚拟主机),要么在执行大选择时进行大更改,要么在使用后不释放准备好的语句,就像里克詹姆斯所说的那样。 (想让帖子有用,但我没有名气,对不起瑞克)

我无法确定“table_definition_cache”的增量是否会起作用,因为系统管理员直到现在仍然不会更改该值,但如果您遇到同样的问题并且可以修改它,值得尝试。

我当前的解决方案是将查询字符串中的所有视图更改为非视图或子查询,这对我有用,但问题仍然悬而未决。

例如。来自

select myview.id, myview.name
from myview
inner join other_table on ...
where myview.id=?

进入

select x.id, x.name
from (select id,name from mytable) x
inner join other_table on ...
where x.id=?

【讨论】:

以上是关于MySql“视图”、“准备好的语句”和“准备好的语句需要重新准备”的主要内容,如果未能解决你的问题,请参考以下文章

Python MySql Connector 准备好的语句和字典类

如何在 python Cassandra 驱动程序中的物化视图上使用准备好的语句?

准备好的语句,`WHERE .. IN(..)` 查询和排序 - 使用 MySQL

用 PDO 和准备好的语句替换 mysql_* 函数

我啥时候应该使用准备好的语句?

如何使用 MySQL 准备好的语句缓存?