我正在关注此Automatic Partition Maintenance in MySQL教程,该教程详细介绍了一种基于日期范围删除和添加mySQL表分区的通用方法。
这个想法是,您可以在一定时间后自动抛弃旧的表数据,并根据需要为当前数据创建新的表分区。
但是,由于我的网站很可能托管在“共享的”提供程序包上,因此我似乎无法使用mySQL事件。
因此,我要交叉使用第一个教程中描述的存储过程,以及使用此Stack Overflow答案中详细介绍的方法并进行一些修改的另一种调用方法:Partition maintainance script for Mysql
在我的本地测试机上,我想从Webmin将PHP脚本作为CRON作业运行。
当我从Adminer(具有与phpMyAdmin类似的功能)运行存储过程时,使用mySQL test database,它们按预期执行-分区被删除,整个过程需要几分钟完成。
但是,当我从Webmin运行修改后的PHP脚本作为CRON作业时,似乎什么也没发生。没有错误,但是脚本立即返回“ OK”。
类似地,当我从LAMP机器的外壳运行脚本时,脚本立即返回“ OK”。
这是PHP脚本:
#!/usr/bin/env php
<?php
$connection = mysqli_connect('localhost', 'my_username', 'my_password', 'employees');
$result = mysqli_query($connection, "CALL perform_partition_maintenance('employees', 'titles', 3, 216, 5)") or die('Query fail: ' . mysqli_error($connection));
if ($result)
echo "OK";
else
echo "FAIL";
mysqli_close($connection);
对于任何可能会出错的建议,我将不胜感激。
更新
根据Nick的建议,我一直在添加许多调试语句。我走了一条略有不同的路线,因为这样做比较容易-许多新的“入文件”语句。
但是我所观察到的使我感到困惑。以下是存储过程的一小部分:
OPEN cur1;
read_loop: LOOP
FETCH cur1 INTO current_partition_name;
IF done THEN
LEAVE read_loop;
END IF;
IF ! @first AND p_seconds_to_sleep > 0 THEN
SELECT CONCAT('Sleeping for ', p_seconds_to_sleep, ' seconds');
SELECT SLEEP(p_seconds_to_sleep);
END IF;
SELECT CONCAT('Dropping partition: ', current_partition_name);
...
SET @first = FALSE;
END LOOP;
CLOSE cur1;
所有内容均取自Geoff Montee页面上的网络教程,未经修改,并且在其他情况下也可以正常使用(即,在Adminer中,从sql控制台开始-只是不与PHP脚本结合使用)。 但是,当我注释掉以下行时:
SELECT CONCAT('Dropping partition: ', current_partition_name);
一切正常,但是当我把那行放回去时脚本会阻塞。我对此毫无意义。特别是因为-在测试中-我将“ current_partition_name”写到磁盘上的文件中,以进行循环的前三个迭代,并且在这种情况下引用该字符串不会引起任何问题。这很奇怪。
This other (apparently unresolved) stackoverflow question听起来有些相似。
答案 0 :(得分:0)
最近,我意识到当表具有外键时分区是不可用的。我不确定我第一次探索分区时是如何错过这个基本细节的。
非常不幸,因为它使整个练习变得多余。我将研究一种涉及常规表删除的解决方案,并解决所有相关的麻烦。
另外,我还不了解为什么要注释掉Geoff Montee的存储过程中的这一行对于使函数从PHP调用成功运行至关重要。我很想把它归结为解释器错误(我在测试环境中运行mySQL 5.5.62),但是如前所述,从Adminer启动时,存储过程可以完美执行。