文档

使用说明

更新时间:

PolarDB MySQL版多主集群(库表)实现从一写多读架构到多写多读多主架构的升级;支持不同数据库或不同数据对象在不同计算节点并发写入;支持数据库和数据对象跨节点动态调度,秒级完成切换,极大提升实例整体并发读写能力。数据对象目前包括如下对象:表(Table)、视图(View)、触发器(Trigger)、定时任务(Event)、存储过程(Procedure)、自定义函数(Function)。本文介绍多主集群(库表)的使用说明。

前提条件

使用限制

  • 每个数据库或数据对象的数据只能通过一个节点写入。没有分配数据库或数据对象的节点,不能进行读写操作。默认情况下,按照数据库的维度进行操作,如果需要按照数据对象的维度进行操作,需要使用指定的语法切换。

  • 不支持跨RW节点的数据查询。如果一个查询SQL中包含多个RW节点上的数据库或数据对象,系统则会报错。建议您先把所有数据库或数据对象的访问点调整到其中一个RW节点上,再进行查询操作。

  • 仅提供集群地址,不支持主地址。

  • 数据库访问点切换支持以下模式:

    • 如果使用数据库隔离级别,则需要切换数据库访问点。

    • 如果使用数据对象隔离级别,则需要切换数据对象访问点。

创建数据库时指定RW节点

在指定的RW节点上创建数据库。语法结构如下:

CREATE DATABASE name [POLARDB_WRITE_NODE master_id];
说明
  • 在数据库隔离级别维度的操作模式下,每个数据库的数据只能通过一个节点写入。

  • 如果上述语法中省略了[POLARDB_WRITE_NODE master_id],那么创建数据库时就会参考loose_innodb_mm_default_master_id参数的值来指定创建数据库的RW节点。如果loose_innodb_mm_default_master_id参数的值为0,系统则随机指定一个RW节点来创建数据库。

示例:在RW1上创建一个数据库db1

CREATE DATABASE db1 POLARDB_WRITE_NODE 1;

如果需要在RW2上创建数据库db1,把上述示例中的1换成2即可。

删除在指定RW节点上创建的数据库

删除在指定RW节点上创建的数据库。语法结构如下:

DROP DATABASE name;

示例:删除在RW1节点上创建的数据库db1

DROP DATABASE db1;

删除数据库时,无需指定POLARDB_WRITE_NODE。

数据库访问点切换

把数据库的访问点切换到其他RW节点上。语法结构如下:

ALTER DATABASE name POLARDB_WRITE_NODE master_id;

示例:把数据库db1切换到RW2上。

ALTER DATABASE db1 POLARDB_WRITE_NODE 2;
说明

正常情况下,访问点切换是一个耗时的操作。具体执行时间取决于以下两个因素:

  • 数据库下表的个数。数量越多,切换速度越慢。

  • 切换时数据库的DML压力。压力越大,切换速度越慢。

数据库隔离级别切换为数据对象隔离级别

默认情况下,多主集群隔离级别是数据库级别,即同一个数据库下的所有数据对象只能在一个RW节点上访问。如果想让同一个数据库下的所有数据对象通过多个RW访问,那么就需要把数据库隔离级别修改成数据对象隔离级别。语法结构如下:

ALTER DATABASE name TO TABLE_LOCK POLARDB_WRITE_NODE master_id;

其中name为数据库的名称。master_id为数据对象的访问点。

示例:把数据库db1的数据对象隔离级别改为数据库隔离级别,并且设置访问点为RW2。

ALTER DATABASE db1 TO TABLE_LOCK POLARDB_WRITE_NODE 2;
说明

正常情况下,隔离级别切换是一个耗时的操作。具体执行时间取决于以下两个因素:

  • 数据库下的所有对象的个数。数量越多,切换速度越慢。

  • 切换时数据库的DML压力。压力越大,切换速度越慢。

数据对象隔离级别切换为数据库隔离级别

如果将一个数据库的最小粒度改为数据对象级别后,再恢复成数据库隔离级别以方便管理,可以使用如下的切换语句:

ALTER DATABASE name TO DB_LOCK POLARDB_WRITE_NODE master_id;

其中name为数据库的名称。master_id为数据库的访问点。

示例:把数据库db1的数据对象隔离级别改为数据库隔离级别,并且设置访问点是RW1。

ALTER DATABASE db1 TO DB_LOCK POLARDB_WRITE_NODE 1;
说明

正常情况下,隔离级别切换是一个耗时的操作。具体执行时间取决于以下两个因素:

  • 数据库下的所有对象的个数。数量越多,切换速度越慢。

  • 切换时数据库的DML压力。压力越大,切换速度越慢。

数据对象访问点切换

多主集群的隔离级别调整为数据对象级别后,同一个数据库下,可能会有多个对象类型,包括TABLE、VIEW、TRIGGER、FUNCTION、PROCEDURE、EVENT。如果需要切换这些对象的访问点,可以使用如下的切换语句:

ALTER obj_type name POLARDB_WRITE_NODE master_id;

其中obj_type可选的值分别为:TABLE、VIEW、TRIGGER、FUNCTION、PROCEDURE、EVENT。name为数据对象的名称。

示例1:把数据库db1下的t1表的访问点切换到RW3。

ALTER TABLE db1.t1 POLARDB_WRITE_NODE 3;

示例2:把当前数据库下的t2 VIEW的访问点切换到RW2。

ALTER VIEW t2 POLARDB_WRITE_NODE 2;

示例3:把数据库db2下的function f1和function f2的访问点切换到RW1。

ALTER FUNCTION db2.f1, db2.f2 POLARDB_WRITE_NODE 1;
说明

正常情况下,访问点切换是一个耗时的操作。具体执行时间取决于以下因素:

  • 切换时数据对象的DML压力。压力越大,切换速度越慢。

  • 对象之间可能会有关联,如果关联对象的访问点没有在同一个RW上,可能会导致对象失效。

    例如,视图VIEW1底层依赖表t1,但是视图VIEW1的访问点在RW1,而表t1的访问点在RW2。那么我们在RW1上访问视图VIEW1时会访问出错。同理,如果FUNCTION、PROCEDURE、EVENT引用的对象没有正确的访问点,也会导致执行失败。TRIGGER和TABLE的访问点不在一起,也会导致TABLE无法修改数据。

  • 如果表t1和t2之间有外键约束关系,那么修改任意一个表的访问点,会自动修改另外一个表的访问点。

指定SQL语句执行的RW节点

重要

该功能仅适用于非数据查询的语句,例如查询information_schema、查询status变量等。如果需要查询数据,例如查询语句SELECT * FROM table1,不需要指定RW节点,数据库代理会自动选择正确的RW节点执行查询。

如果需要把某条SQL语句发送到指定的RW节点,则需要执行以下SQL语句锁定某个RW节点:

ALTER SESSION POLARDB_WRITE_NODE master_id;

示例:查询RW1节点上innodb_buffer_pool_size这个变量的值。

ALTER SESSION POLARDB_WRITE_NODE 1;   #把SQL语句发送到RW1节点。
SHOW VARIABLES LIKE 'innodb_buffer_pool_size';  #查询RW1节点上innodb_buffer_pool_size的值。
说明

如果在执行某条SQL语句时不指定RW节点,那么数据库代理会随机选择一个RW节点执行该SQL语句。

执行以下命令可以解锁指定执行SQL语句的RW节点:

RESET SESSION POLARDB_WRITE_NODE;

查询节点信息

  • 执行以下命令可以查询某个RW节点上的数据库分布情况:

    ALTER SESSION POLARDB_WRITE_NODE master_id;
    SELECT * FROM INFORMATION_SCHEMA.INNODB_MASTER_GLOBAL_LOCK_INFO WHERE LOCK_MODE = 'SLS_X';

    示例:查询RW1节点上的数据库分布情况。

    ALTER SESSION POLARDB_WRITE_NODE 1;
    SELECT * FROM INFORMATION_SCHEMA.INNODB_MASTER_GLOBAL_LOCK_INFO WHERE LOCK_MODE = 'SLS_X';

    查询结果如下:

     SELECT * FROM INFORMATION_SCHEMA.INNODB_MASTER_GLOBAL_LOCK_INFO WHERE LOCK_MODE = 'SLS_X';
    
    +------------+---------------------+----------+--------------+-----------+----------+-------------+-------------+---------------------+-----------------+
    | table_name | table_id            | space_id | s_lock_count | lock_mode | object   | current_lsn | hold_thread | hold_start_time     | hold_total_time |
    +------------+---------------------+----------+--------------+-----------+----------+-------------+-------------+---------------------+-----------------+
    | test3/f1   | 9149389368458135753 |        0 |            0 | SLS_X     | function |    28076635 |          17 | 2024-07-10 21:35:20 |             214 |
    | test3/e1   | 9149389368458332874 |        0 |            0 | SLS_X     | event    |    28077248 |          17 | 2024-07-10 21:35:30 |             204 |
    | test3/v1   | 9149389368457234649 |        0 |            0 | SLS_X     | view     |    28075972 |          17 | 2024-07-10 21:35:08 |             226 |
    | sbtest     | 2107518311328629409 |        0 |            0 | SLS_X     | db       |    28034927 |  4294967295 | 2024-07-07 23:04:41 |          254053 |
    | test       | 7190879906290573778 |        0 |            0 | SLS_X     | db       |    28034927 |  4294967295 | 2024-07-10 11:20:57 |           37077 |
    | test2      | 3381728963524265351 |        0 |            0 | SLS_X     | db       |    28034927 |  4294967295 | 2024-07-10 11:13:09 |           37545 |
    +------------+---------------------+----------+--------------+-----------+----------+-------------+-------------+---------------------+-----------------+
    
    6 rows in set (0.00 sec)

    上述查询结果中的每一行都是一个数据库或数据对象的信息(虽然列名是table_name)。上图中,sbtesttesttest2分别是数据库的隔离级别,function test3.f1是数据对象隔离级别,event test3.e1是数据对象隔离级别,view test3.v1也是数据对象隔离级别。此外,可能会查询出名称为mysql/global_ddl_lock且object类型为Table的信息,这个是内部使用的信息,您无需关注。

  • 执行以下命令可以查询整个集群上所有数据库的分布情况:

    说明

    仅支持通过高权限账号查询,您不能通过新建的账号进行查询。

    SELECT * FROM INFORMATION_SCHEMA.INNODB_CC_GLOBAL_LOCK_INFO WHERE LOCK_MODE = 'SLS_X';

    查询结果如下:

    mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_CC_GLOBAL_LOCK_INFO WHERE LOCK_MODE = 'SLS_X';
    +-----------+------------+---------------------+-----------+-----------+-------------+---------------------+-----------------+
    | master_id | table_name | table_id            | lock_mode | object    | current_lsn | hold_start_time     | hold_total_time |
    +-----------+------------+---------------------+-----------+-----------+-------------+---------------------+-----------------+
    |         1 | test3/v1   | 9149389368457234649 | SLS_X     | view      |    28075972 | 2024-07-10 21:35:08 |             754 |
    |         2 | test5/t1   | 9149389447232697561 | SLS_X     | table     |     7256175 | 2024-07-10 21:46:36 |              66 |
    |         1 | test2      | 3381728963524265351 | SLS_X     | db        |    28034927 | 2024-07-10 11:13:09 |           38073 |
    |         2 | test4      | 3381728963524272009 | SLS_X     | db        |     7255352 | 2024-07-10 21:46:27 |              75 |
    |         1 | test3/f1   | 9149389368458135753 | SLS_X     | function  |    28076635 | 2024-07-10 21:35:20 |             742 |
    |         1 | test3/e1   | 9149389368458332874 | SLS_X     | event     |    28077248 | 2024-07-10 21:35:30 |             732 |
    |         1 | test       | 7190879906290573778 | SLS_X     | db        |    28034927 | 2024-07-10 11:20:57 |           37605 |
    |         2 | test5/p1   | 9149389447233473757 | SLS_X     | procedure |     7257051 | 2024-07-10 21:46:45 |              57 |
    |         1 | sbtest     | 2107518311328629409 | SLS_X     | db        |    28034927 | 2024-07-07 23:04:41 |          254581 |
    +-----------+------------+---------------------+-----------+-----------+-------------+---------------------+-----------------+
    
    9 rows in set (0.00 sec)

    上述查询结果中的每一行就是一个数据库或数据对象的信息(虽然列名是table_name),表示这个数据库或数据对象是在对应的RW上。此外,可能会查询出名称为mysql/global_ddl_lock且object类型为Table的信息,这个是内部使用的信息,您无需关注。

如何设置Binlog

多主集群(库表)100%兼容MySQL的Binlog,它整合集群中所有RW节点上的操作日志,产生出全局统一、逻辑有序的Binlog日志。

您可以通过loose_polar_log_bin来开启多主集群(库表)的Binlog功能,通过binlog_expire_logs_seconds来设置多主集群(库表)Binlog的保存时长。详细信息请参见开启Binlog

说明

多主集群(库表)可以作为数据传输服务DTS的源端和目的端,来进行数据的单向或双向同步。