頭一次使用mysql表分區,遇到不少的問題,現在總結下遇到的問題和解決方案。
1、如果分區值類型不是整型值,會出現如下錯誤:
[Err] 1697 - VALUES value for partition 'p0' must have type INT
分區值必須為整型值。例如下方的建表就會出這樣的錯誤:
create table rms (d date) partition by range (d) (partition p0 VALUES LESS THAN ('1995-01-01'), partition p1 VALUES LESS THAN ('2010-01-01'));
類似的解決方案,改成下方的樣子就可以通過:
create table rms (d TIMESTAMP) partition by range (UNIX_TIMESTAMP(d)) (partition p0 VALUES LESS THAN (UNIX_TIMESTAMP('1995-01-01')), partition p1 VALUES LESS THAN (UNIX_TIMESTAMP('2010-01-01')));
2、如果上方的錯誤示例,改成如下:
create table rms (d DATE) partition by range (UNIX_TIMESTAMP(d)) (partition p0 VALUES LESS THAN (UNIX_TIMESTAMP('1995-01-01')), partition p1 VALUES LESS THAN (UNIX_TIMESTAMP('2010-01-01')));
就會出現如下錯誤:
[Err] 1486 - Constant, random or timezone-dependent expressions in (sub)partitioning function are not allowed
這是因為UNIX_TIMESTAMP函數在轉換DATE類型值時,需要考慮時區問題。以上錯誤信息的意思就是:常量、隨機值和時區相關的表達式不能用於分區表達式中。
可以反過來考慮,假如mysql所在的系統今天如果更改了當前時區,那就會有可能出現更改前與更改后,同一日期的數據存儲在不同分區的現象了。常量與隨機值也同樣如此,可能會因不同環境和時間出現不同的值。
如果真要存儲DATE或DATETIME類型,那么可以改成以下解決方案:
create table rms (d DATE) partition by range (to_days(d)) (partition p0 VALUES LESS THAN (to_days('1995-01-01')), partition p1 VALUES LESS THAN (to_days('2010-01-01')));
3、如果主鍵或唯一索引鍵沒包含分區使用的鍵,比如:
CREATE TABLE T1 ( id int(8) NOT NULL AUTO_INCREMENT, createtime datetime NOT NULL, PRIMARY KEY (id) ) PARTITION BY RANGE(TO_DAYS (createtime)) ( PARTITION p0 VALUES LESS THAN (TO_DAYS('2010-04-15')), PARTITION p1 VALUES LESS THAN (TO_DAYS('2010-05-01')), PARTITION p2 VALUES LESS THAN (TO_DAYS('2010-05-15')) );
就會出錯:[Err] 1503 - A PRIMARY KEY must include all columns in the table's partitioning function
意思是主鍵必須包括所有分區函數中所有字段。
不僅是主鍵,連唯一索引鍵都會如此。以下建表SQL都會出錯:
CREATE TABLE t1 ( col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col2) ) PARTITION BY HASH(col3) PARTITIONS 4; CREATE TABLE t2 ( col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1), UNIQUE KEY (col3) ) PARTITION BY HASH(col1 + col3) PARTITIONS 4;
CREATE TABLE t3 ( col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col2), UNIQUE KEY (col3) ) PARTITION BY HASH(col1 + col3) PARTITIONS 4;
改成以下方式則可通過:
CREATE TABLE t1 ( col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col2, col3) ) PARTITION BY HASH(col3) PARTITIONS 4; CREATE TABLE t2 ( col1 INT NOT NULL, col2 DATE NOT NULL, col3 INT NOT NULL, col4 INT NOT NULL, UNIQUE KEY (col1, col3) ) PARTITION BY HASH(col1 + col3) PARTITIONS 4;
4、另外,如果使用一些強制轉換函數,分區不支持:
CREATE TABLE part_date1 ( c1 int default NULL, c2 varchar(30) default NULL, c3 date default NULL) engine=myisam partition by range (cast(date_format(c3,'%Y%m%d') as int)) (PARTITION p0 VALUES LESS THAN (19950101), PARTITION p1 VALUES LESS THAN (19960101) , PARTITION p2 VALUES LESS THAN (19970101));
[Err] 1564 - This partition function is not allowed。
參考文章:
https://blog.csdn.net/zhang168/article/details/46911305/
https://dev.mysql.com/doc/refman/5.6/en/partitioning-limitations-partitioning-keys-unique-keys.html