web-dev-qa-db-ja.com

パーティションを削除するにはどうすればよいですか?

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はいくつかのファイルを構成する必要があると思いますが、その理由はわかりません。

解けますか

3
user2481179

古いデータを削除するために使用しているメカニズムを使用するかどうかはわかりませんが、それはあなたがやりたいことなので、これを回避する方法があります。

あなたが見ているものは、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は、サーバーに「このエラーが発生した場合、エラーをスローする代わりに、この空のブロックに表示されるコードを実行します」と伝えています。 BEGINENDの間にコードはありませんが、MySQLは気にせず、これによりエラー1505が抑制されます。

BEGIN...」の前と「DECLARE...」の前のALTEREND;は、そのCONTINUE HANDLERのスコープを単一のALTER TABLEに限定し、他のステートメントが同じ後でストアドプロシージャ(またはプロシージャによって呼び出される任意のプロシージャ)のエラーコードは無視されません。これはALTER TABLEの後の次のENDの前のステートメントがnotを意味することに注意してください。これは、END;の後、CONTINUE HANDLERがスコープ外になり、後続のエラーをトラップしないことを意味します。

2

テーブルを分割する構文は次のとおりです。

ALTER TABLE t1
    PARTITION BY HASH(id)
    PARTITIONS 8;

しかし、最初に docs を注意深く読むことをお勧めします。

テーブルを分割する前に、まず考える必要があります:

  • データのパーティションが作成されるフィールド(日付別、ユーザー別など)では、適切なフィールドを選択するとパフォーマンスが劇的に向上するため、これは重要です
  • データを分割するために使用するアルゴリズム。テーブルを分割する一般的な規則ではないため、最善の決定を行うには、これを読む必要があります
0
Stephan

ステファンとマイケル-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;
0
user24954