MySQL 5.6でパーティションが作成されていないテーブルmy_table
があります。そして、このコードを実行すると、my_table
の手順でパーティションを作成しようとしています。
alter table my_table remove partitioning
このエラーが発生します:
1505 - Partition management on a not partitioned table is not possible
しかし、MySQLバージョン5.5で上記のコードを実行すると、このコードを実行できます。
My_tableがパーティションを作成していて、上記のコードを実行すると、MySQL 5.5だけでなく、MySQL 5.6も実行できます。
このコードを実行できる場合、MySQL 5.6はいくつかのファイルを構成する必要があると思いますが、その理由はわかりません。
解けますか
古いデータを削除するために使用しているメカニズムを使用するかどうかはわかりませんが、それはあなたがやりたいことなので、これを回避する方法があります。
あなたが見ているものは、MySQL 5.5とMySQL 5.6の間の動作の文書化されていない互換性のない変更のようです-間違いなく、本当の問題は、テーブルがパーティション化されていない場合、ステートメントがMySQL 5.5で有効であるべきではないことです。
MySQL 5.5.30(エラーなし)および5.6.10(エラー)で見られる動作を確認しました。
手順でパーティションを作成しようとしています
ストアドプロシージャとはどういう意味ですか?
その場合は、特別に記述された CONTINUE HANDLER
を使用して、ストアドプロシージャがその特定のエラーコードを無視できるようにすることができます。
以下は、MySQL 5.5と5.6の両方で機能します。
DELIMITER $$
DROP PROCEDURE IF EXISTS `test`.`test_continue_handler` $$
CREATE PROCEDURE `test`.`test_continue_handler` ()
BEGIN
-- you may have some code that executes before the ALTER TABLE, here
BEGIN
DECLARE CONTINUE HANDLER FOR 1505 BEGIN END;
ALTER TABLE t1 REMOVE PARTITIONING;
END;
SELECT 'that worked okay' AS message; -- remove this, your usual code after the ALTER TABLE goes here
END $$
DELIMITER ;
mysql> call test_continue_handler;
+------------------+
| message |
+------------------+
| that worked okay |
+------------------+
1 row in set (0.06 sec)
Query OK, 0 rows affected (0.07 sec)
BEGIN END;
の後の1505
は、サーバーに「このエラーが発生した場合、エラーをスローする代わりに、この空のブロックに表示されるコードを実行します」と伝えています。 BEGIN
とEND
の間にコードはありませんが、MySQLは気にせず、これによりエラー1505が抑制されます。
「BEGIN
...」の前と「DECLARE
...」の前のALTER
とEND;
は、そのCONTINUE HANDLER
のスコープを単一のALTER TABLE
に限定し、他のステートメントが同じ後でストアドプロシージャ(またはプロシージャによって呼び出される任意のプロシージャ)のエラーコードは無視されません。これはALTER TABLE
の後の次のEND
の前のステートメントがnotを意味することに注意してください。これは、END;
の後、CONTINUE HANDLER
がスコープ外になり、後続のエラーをトラップしないことを意味します。
ステファンとマイケル-sqlbot、ありがとう。
Stephanによると、手順を実行する前に、テーブルにパーティションを作成しました。それで、正常に実行できます。
そして、Michael-sqlbotによると、私は自分の手順を変更し、コードに「DECLARE CONTINUE HANDLER FOR 1505 BEGIN END;」を追加しました。したがって、手順を実行する前にテーブルにパーティションを作成しませんでした。プロシージャも正常に実行できます。
上記の2つの方法を比較して、Michael-sqlbotの方法を選択しました。これにより、最初の実行に関する問題がこの方法で解決されます。もう一度ありがとうございます。
以下は変更後の私の手順です。
-- general_procedure
create procedure general_procedure(in tablenamein varchar(50),in intervalHour int,in newIntervalNum int)
general_pro:begin
declare maxMonitTime datetime default SYSDATE();
declare maxMonitTimeStr varchar(50);
declare minMonitTime datetime default SYSDATE();
declare minMonitTimeStr varchar(50);
declare recoidNum int default 0;
DECLARE CONTINUE HANDLER FOR 1505 BEGIN END;
if tablenamein is null then
leave general_pro;
end if;
if intervalHour <= 0 then
set intervalHour = 6;
end if;
if newIntervalNum <= 0 then
set newIntervalNum = 1;
end if;
select count(*) into recoidNum from table_fen_qu where tablename=tablenamein and backupflag=0;
if recoidNum > 0 then
select monittime into maxMonitTime from table_fen_qu where tablename=tablenamein and backupflag=0 order by monittime desc limit 1;
if maxMonitTime is null then
set maxMonitTime = SYSDATE();
end if;
set recoidNum = timestampdiff(hour,SYSDATE(),DATE_SUB(maxMonitTime,INTERVAL 3 DAY));
if recoidNum <= 0 then
set recoidNum = 1;
while recoidNum <= newIntervalNum do
set maxMonitTime = ADDDATE(maxMonitTime,INTERVAL intervalHour HOUR);
set maxMonitTimeStr = CONCAT('p',DATE_FORMAT(maxMonitTime,"%Y%m%d%H%i%s"));
set @v_add_s = CONCAT('ALTER TABLE ',tablenamein,' ADD PARTITION (PARTITION ',maxMonitTimeStr,' VALUES LESS THAN (\'',maxMonitTime,'\') ENGINE = InnoDB )');
prepare stmt from @v_add_s;
execute stmt;
deallocate prepare stmt;
insert into table_fen_qu(fenquname,tablename,monittime,backupflag) VALUES(maxMonitTimeStr,tablenamein,maxMonitTime,0);
set recoidNum = recoidNum + 1;
end while;
end if;
else
set @v_del_s = CONCAT('ALTER TABLE ',tablenamein,' remove partitioning');
prepare stmt from @v_del_s;
execute stmt;
deallocate prepare stmt;
delete from table_fen_qu where tablename = tablenamein;
set @sele = CONCAT('select min(moint_time),max(moint_time) into @mintime,@maxtime from ',tablenamein);
prepare stmt from @sele;
execute stmt;
deallocate prepare stmt;
set minMonitTime = @mintime;
set maxMonitTime = @maxtime;
if minMonitTime is null then
set minMonitTimeStr = CONCAT(DATE_FORMAT(ADDDATE(SYSDATE(),INTERVAL 4 DAY),'%Y-%m-%d'),' 00:00:00');
set minMonitTime = STR_TO_DATE(minMonitTimeStr,'%Y-%m-%d %H:%i:%s');
set minMonitTimeStr = CONCAT('p',DATE_FORMAT(minMonitTime,"%Y%m%d%H%i%s"));
set @v_add_s = CONCAT('ALTER TABLE ',tablenamein,' PARTITION BY RANGE COLUMNS(moint_time) (PARTITION ',minMonitTimeStr,' VALUES LESS THAN (\'',minMonitTime,'\') ENGINE = InnoDB);');
prepare stmt from @v_add_s;
execute stmt;
deallocate prepare stmt;
insert into table_fen_qu(fenquname,tablename,monittime,backupflag) VALUES(minMonitTimeStr,tablenamein,minMonitTime,0);
else
set recoidNum = 2;
set minMonitTimeStr = CONCAT(DATE_FORMAT(minMonitTime,'%Y-%m-%d'),' 00:00:00');
set minMonitTime = STR_TO_DATE(minMonitTimeStr,'%Y-%m-%d %H:%i:%s');
set maxMonitTimeStr = CONCAT(DATE_FORMAT(ADDDATE(maxMonitTime,INTERVAL 4 DAY),'%Y-%m-%d'),' 00:00:00');
set maxMonitTime = STR_TO_DATE(maxMonitTimeStr,'%Y-%m-%d %H:%i:%s');
set newIntervalNum = floor(timestampdiff(hour,minMonitTime,maxMonitTime) / intervalHour) + 1;
if newIntervalNum < 12 then
set newIntervalNum = 12;
end if;
set minMonitTimeStr = CONCAT('p',DATE_FORMAT(minMonitTime,"%Y%m%d%H%i%s"));
set @v_add_s = CONCAT('ALTER TABLE ',tablenamein,' PARTITION BY RANGE COLUMNS(moint_time) (PARTITION ',minMonitTimeStr,' VALUES LESS THAN (\'',minMonitTime,'\') ENGINE = InnoDB,');
insert into table_fen_qu(fenquname,tablename,monittime,backupflag) VALUES(minMonitTimeStr,tablenamein,minMonitTime,0);
while recoidNum <= newIntervalNum do
set minMonitTime = ADDDATE(minMonitTime,INTERVAL intervalHour HOUR);
set minMonitTimeStr = CONCAT('p',DATE_FORMAT(minMonitTime,"%Y%m%d%H%i%s"));
set @v_add_s = CONCAT(@v_add_s,'PARTITION ',minMonitTimeStr,' VALUES LESS THAN (\'',minMonitTime,'\') ENGINE = InnoDB,');
insert into table_fen_qu(fenquname,tablename,monittime,backupflag) VALUES(minMonitTimeStr,tablenamein,minMonitTime,0);
set recoidNum = recoidNum + 1;
end while;
set @v_add_s = left(@v_add_s,LENGTH(@v_add_s)-1);
set @v_add_s = CONCAT(@v_add_s,');');
prepare stmt from @v_add_s;
execute stmt;
deallocate prepare stmt;
end if;
end if;
end general_pro;