mysql partitioning with unix_timestamp from variable

 ̄綄美尐妖づ 提交于 2019-12-04 08:57:51

To keep the solution in full sql this is what I have found.

delimiter //
create procedure setup()
begin
  declare d, d2 int;
  set d = unix_timestamp();
  set d2 = unix_timestamp(now() + interval 1 day);

  create table s_time (req_id int not null,
                       ser_id int not null,
                       hel_id int not null,
                       posted int unsigned not null,
                       completed int unsigned not null default 0
                      );

  SET @stmt = concat('alter table s_time PARTITION BY RANGE (completed) (
                      partition p0 values less than (', d, '),
                      partition p1 values less than (', d2, '))');
  PREPARE pStmt FROM @stmt;
  EXECUTE pStmt;
  DEALLOCATE PREPARE pStmt;

end//
delimiter ;
call setup();

The reason of this not working is not so clear, I suspect a bug either in the documentation or in the error message. The error you are receiving is inappropriate, in my opinion.

According to the manual:

The following constructs are not permitted in partitioning expressions:

  • Stored procedures, stored functions, UDFs, or plugins.
  • Declared variables or user variables.

This explains why your table definition fails.

Now, how to get rid of your variable? If you try to remove the declared variable from the partition definition:

CREATE TABLE s_time (
    completed INT UNSIGNED NOT NULL DEFAULT 0
)
PARTITION BY RANGE ( completed  ) (
    PARTITION p0 VALUES LESS THAN ( UNIX_TIMESTAMP() )
);

you will get the same error. However, the MySQL manual states:

It is also possible to use an expression in VALUES LESS THAN clauses. However, MySQL must be able to evaluate the expression's return value as part of a LESS THAN (<) comparison.

According to this definition, UNIX_TIMESTAMP() should be a valid expression. This sentence from the manual is inaccurate to say the least. I am very curious to see if someone else could provide another understanding.

Now, looking at the error message, if you consider the LESS THAN clause as a part of the "partitioning function", then the error message starts making sense:

ERROR 1064 (42000) : Constant, random, or timezone-dependent expression in (sub)partitioning function or in LESS THAN clause are not allowed

By "random", they also mean non-deterministic, which the UNIX_TIMESTAMP() function is by definition.

To achieve what you are trying to do, I see no other solution but using an external script to generate the suitable ALTER TABLE command.

1) Create your initial table:

CREATE TABLE s_time (
    req_id INT NOT NULL,
    ser_id INT NOT NULL,
    hel_id INT NOT NULL,
    posted INT UNSIGNED NOT NULL,
    completed INT UNSIGNED NOT NULL DEFAULT 0
) PARTITION BY RANGE (completed) (
    PARTITION p0 VALUES LESS THAN (0),
    PARTITION p1 VALUES LESS THAN (1)
);

2) Reorganise the partitions every now and then (e.g. with PHP):

<?php
    $query = 
        "ALTER TABLE s_time REORGANIZE PARTITION p0, p1 INTO (
            PARTITION p0 VALUES LESS THAN ($today),
            PARTITION p1 VALUES LESS THAN ($tomorrow)
        )";

See the proof of concept here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!