您可以将分区和二级子分区设置为只读状态,用于保护数据不受任何用户或触发器执行的DML操作的影响。

只读分区如下图所示:只读分区

语法

  • 新建表时创建只读分区
    CREATE TABLE [IF NOT EXISTS] [schema.]table_name
        table_definition [READ {ONLY | WRITE}]
        partition_options;
    其中partition_options为:
    PARTITION BY
        { RANGE{(expr) | COLUMNS(column_list)} }
        [(partition_definition [, partition_definition] ...)]
    partition_definition为:
        PARTITION partition_name
            [VALUES LESS THAN {expr | MAXVALUE}]
            [READ {ONLY | WRITE}]
            [[STORAGE] ENGINE [=] engine_name]
            [COMMENT [=] 'string' ]
            [DATA DIRECTORY [=] 'data_dir']
            [INDEX DIRECTORY [=] 'index_dir']
            [MAX_ROWS [=] max_number_of_rows]
            [MIN_ROWS [=] min_number_of_rows]
            [TABLESPACE [=] tablespace_name]
  • 修改表时创建只读分区
    ALTER TABLE tbl_name
        [alter_option [, alter_option] ...]
        [partition_options]
    其中partition_options为:
    partition_options:
        partition_option [partition_option] ...
    partition_option为:
    partition_option: {
        ADD PARTITION (partition_definition)
    partition_definition为:
        PARTITION partition_name
            [VALUES LESS THAN {expr | MAXVALUE}]
            [READ {ONLY | WRITE}]
            [[STORAGE] ENGINE [=] engine_name]
            [COMMENT [=] 'string' ]
            [DATA DIRECTORY [=] 'data_dir']
            [INDEX DIRECTORY [=] 'index_dir']
            [MAX_ROWS [=] max_number_of_rows]
            [MIN_ROWS [=] min_number_of_rows]
            [TABLESPACE [=] tablespace_name]
    其中alter_option为:
    alter_option: {
        table_options
      | ADD [COLUMN] col_name column_definition
            [FIRST | AFTER col_name]
      | ADD [COLUMN] (col_name column_definition,...)
      | ADD {INDEX | KEY} [index_name]
            [index_type] (key_part,...) [index_option] ...
      | ADD {FULLTEXT | SPATIAL} [INDEX | KEY] [index_name]
            (key_part,...) [index_option] ...
      | ADD [CONSTRAINT [symbol]] PRIMARY KEY
            [index_type] (key_part,...)
            [index_option] ...
      | ADD [CONSTRAINT [symbol]] UNIQUE [INDEX | KEY]
            [index_name] [index_type] (key_part,...)
            [index_option] ...
      | ADD [CONSTRAINT [symbol]] FOREIGN KEY
            [index_name] (col_name,...)
            reference_definition
      | ADD [CONSTRAINT [symbol]] CHECK (expr) [[NOT] ENFORCED]
      | DROP {CHECK | CONSTRAINT} symbol
      | ALTER {CHECK | CONSTRAINT} symbol [NOT] ENFORCED
      | ALGORITHM [=] {DEFAULT | INSTANT | INPLACE | COPY}
      | ALTER [COLUMN] col_name {
            SET DEFAULT {literal | (expr)}
          | SET {VISIBLE | INVISIBLE}
          | DROP DEFAULT
        }
      | ALTER INDEX index_name {VISIBLE | INVISIBLE}
      | CHANGE [COLUMN] old_col_name new_col_name column_definition
            [FIRST | AFTER col_name]
      | [DEFAULT] CHARACTER SET [=] charset_name [COLLATE [=] collation_name]
      | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
      | {DISABLE | ENABLE} KEYS
      | {DISCARD | IMPORT} TABLESPACE
      | DROP [COLUMN] col_name
      | DROP {INDEX | KEY} index_name
      | DROP PRIMARY KEY
      | DROP FOREIGN KEY fk_symbol
      | FORCE
      | LOCK [=] {DEFAULT | NONE | SHARED | EXCLUSIVE}
      | MODIFY [COLUMN] col_name column_definition
            [FIRST | AFTER col_name]
      | ORDER BY col_name [, col_name] ...
      | RENAME COLUMN old_col_name TO new_col_name
      | RENAME {INDEX | KEY} old_index_name TO new_index_name
      | RENAME [TO | AS] new_tbl_name
      | {WITHOUT | WITH} VALIDATION
    }

参数

参数名称 参数说明
table_name 表名称。
expr 分区字段表达式。
column_list 分区字段列表,不支持表达式。
MAXVALUE 最大值。
partition_name 分区名称,同一个表中不可重复。
engine_name 存储引擎名称。
table_options 表选项。
col_name 列名。

注意事项

您不能修改只读分区的数据。如果尝试修改只读分区的数据,系统会报错ERROR HY000: Data in a read-only partition or subpartition cannot be modified.。这里的修改操作不仅仅包括INSERT、UPDATE和DELETE操作,任何对只读分区数据结果产生变化的DDL操作都会被拒绝。

由于添加列不会修改原有的只读数据属性,因此添加列是被允许的。如下:
ALTER TABLE [schema.]table_name ADD col_new varchar(100) DEFAULT 'i am not empty';

示例

创建t1表时,指定t1表的所有分区为只读分区
CREATE TABLE t1 (
  id INT,
  year_col INT
) READ ONLY
PARTITION BY RANGE (year_col) (
  PARTITION p0 VALUES LESS THAN (2001),
  PARTITION p1 VALUES LESS THAN (2010),
  PARTITION p2 VALUES LESS THAN (2020)
);
t1表新增只读分区
ALTER TABLE t1 ADD PARTITION (PARTITION p3 values LESS THAN (2030));
Query OK, 0 rows affected (0.22 sec)
Records: 0  Duplicates: 0  Warnings: 0
新增只读分区后,可以发现新分区仍然为只读分区
SHOW CREATE TABLE t1;
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int(11) DEFAULT NULL,
  `year_col` int(11) DEFAULT NULL
) /*!99990 800020201 READ ONLY */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (`year_col`)
(PARTITION p0 VALUES LESS THAN (2001) ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (2010) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (2020) ENGINE = InnoDB,
 PARTITION p3 VALUES LESS THAN (2030) ENGINE = InnoDB) */ |
+-------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
t1表创建混合属性的分区
CREATE TABLE t1 (
    id INT,
    year_col INT
) READ WRITE
PARTITION BY RANGE (year_col) (
    PARTITION p0 VALUES LESS THAN (2001) READ ONLY,
    PARTITION p1 VALUES LESS THAN (2010),
    PARTITION p2 VALUES LESS THAN (2020) READ ONLY
);

如何查看只读分区

目前只能通过SHOW CREATE命令查询分区表的分区只读属性,例如:
show create table t1;
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| t1    | CREATE TABLE `t1` (
  `id` int(11) DEFAULT NULL,
  `year_col` int(11) DEFAULT NULL
) /*!99990 800020201 READ WRITE */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
/*!50100 PARTITION BY RANGE (`year_col`)
(PARTITION p0 VALUES LESS THAN (2001) */ /*!99990 800020201  READ ONLY */
/*!50100  ENGINE = InnoDB,
 PARTITION p1 VALUES LESS THAN (2010) ENGINE = InnoDB,
 PARTITION p2 VALUES LESS THAN (2020) */ /*!99990 800020201  READ ONLY */
/*!50100  ENGINE = InnoDB) */ |
+-------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)