Project: ShardingSphere (App Definition and Development / Database)
File: 2022_07_26_DistSQL_Applications_Building_a_Dynamic_Distributed_Database.en.md

+++ title = "DistSQL Applications: Building a Dynamic Distributed Database" weight = 69 chapter = true +++ Ever since the release of , has been providing strong dynamic management capabilities to the ShardingSphere ecosystem. Thanks to DistSQL, users have been empowered to do the following: Create logical databases online. Dynamically configure rules (i.e. sharding, data encryption, read/write splitting, database discovery, shadow DB, and global rules). Adjust storage resources in real-time. Switch transaction types instantly. Turn SQL logs on and off at any time. Preview the SQL routing results. At the same time, in the context of increasingly diversified scenarios, more and more DistSQL features are being created and a variety of valuable syntaxes have been gaining popularity among users. This post takes data sharding as an example to illustrate DistSQLs application scenarios and related sharding methods. A series of DistSQL statements are concatenated through practical cases, to give you a complete set of practical DistSQL sharding management schemes, which create and maintain distributed databases through dynamic management. The following DistSQL will be used in this example: Required scenarios Create two sharding tables: `torder` and `torder_item`. For both tables, database shards are carried out with the `userid` field, and table shards with the `orderid` field. The number of shards is 2 databases * 3 tables. As shown in the figure below: Setting up the environment 1.Prepare a MySQL database instance for access. Create two new databases: `demods0` and `demods1`. Here we take MySQL as an example, but you can also use PostgreSQL or openGauss databases. 2.Deploy and . ZooKeeper acts as a governance center and stores ShardingSphere metadata information. 3.Configure `server.yaml` in the `Proxy conf` directory as follows: ```yaml mode: type: Cluster repository: type: ZooKeeper props: namespace: governance_ds server-lists: localhost:2181 # ZooKeeper address retryIntervalMilliseconds: 500 timeToLiveSeconds: 60 maxRetries: 3 operationTimeoutMilliseconds: 500 overwrite: false rules: !AUTHORITY users: root@%:root ``` 4.Start ShardingSphere-Proxy and connect it to Proxy using a client, for example: ```bash mysql -h 127.0.0.1 -P 3307 -u root -p ``` Creating a distributed database ```sql CREATE DATABASE sharding_db; USE sharding_db; ``` Adding storage resources 1.Add storage resources corresponding to the prepared database. ``` ADD RESOURCE ds_0 ( HOST=127.0.0.1, PORT=3306, DB=demods0, USER=root, PASSWORD=123456 ), ds_1( HOST=127.0.0.1, PORT=3306, DB=demods1, USER=root, PASSWORD=123456 ); ``` 2.View storage resources ``` mysql> SHOW DATABASE RESOURCES\G; row * name: ds_1 type: MySQL host: 127.0.0.1 port: 3306 db: demods1 -- Omit partial attributes row * name: ds_0 type: MySQL host: 127.0.0.1 port: 3306 db: demods0 -- Omit partial attributes ``` Adding \G to the query statement aims to make the output format more readable, and it is not a must. Creating sharding rules ShardingSpheres sharding rules support regular sharding and automatic sharding. Both sharding methods have the same effect. The difference is that the configuration of automatic sharding is more concise, while regular sharding is more flexible and independent. Please refer to the following links for more details on automatic sharding: Next, well adopt regular sharding and use the `INLINE` expression algorithm to implement the sharding scenarios described in the requirements. Primary key generator The primary key generator can generate a secure and unique primary key for a data table in a distributed scenario. For details, refer to the document . 1.Create the primary key generator. ``` CREATE SHARDING KEY GENERATOR snowflakekeygenerator ( TYPE(NAME=SNOWFLAKE) ); ``` 2.Query primary key generator ``` mysql> SHOW SHARDING KEY GENERATORS; +-+--+-+ | name | type | props | +-+--+-+ | snowflakekeygenerator | snowflake | {} | +-+--+-+ 1 row in set

sec) ``` Sharding algorithm 1.Create a database sharding algorithm, used by `torder` and `torder_item` in common. ``` -- Modulo 2 based on user_id in database sharding CREATE SHARDING ALGORITHM database_inline ( TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="ds${userid % 2}")) ); ``` 2.Create different table shards algorithms for `torder` and `torder_item`. ``` -- Modulo 3 based on order_id in table sharding CREATE SHARDING ALGORITHM torderinline ( TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="torder${order_id % 3}")) ); CREATE SHARDING ALGORITHM torderitem_inline ( TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="torderitem${orderid % 3}")) ); ``` 3.Query sharding algorithm ``` mysql> SHOW SHARDING ALGORITHMS; ++--++ | name | type | props | ++--++ | databaseinline | inline | algorithm-expression=ds${user_id % 2} | | torderinline | inline | algorithm-expression=torder${order_id % 3} | | torderiteminline | inline | algorithm-expression=torderitem${order_id % 3} | ++--++ 3 rows in set (0.00 sec) ``` Default sharding strategy Sharding strategy consists of sharding key and sharding algorithm. Please refer to for its concept. Sharding strategy consists of `databaseStrategy` and `tableStrategy`. Since `torder` and `torder_item` have the same database sharding field and sharding algorithm, we create a default strategy that will be used by all shard tables with no sharding strategy configured: 1.Create a default database sharding strategy ``` CREATE DEFAULT SHARDING DATABASE STRATEGY ( TYPE=STANDARD,SHARDINGCOLUMN=userid,SHARDINGALGORITHM=databaseinline ); ``` 2.Query default strategy ``` mysql> SHOW DEFAULT SHARDING STRATEGY\G; row * name: TABLE type: NONE sharding_column: shardingalgorithmname: shardingalgorithmtype: shardingalgorithmprops: row * name: DATABASE type: STANDARD shardingcolumn: userid shardingalgorithmname: database_inline shardingalgorithmtype: inline shardingalgorithmprops: {algorithm-expression=ds${userid % 2}} 2 rows in set (0.00 sec) ``` The default table sharding strategy is not configured, so the default strategy of `TABLE` is `NONE`. Sharding rules The primary key generator and sharding algorithm are both ready. Now create sharding rules. 1.`t_order` ``` CREATE SHARDING TABLE RULE t_order ( DATANODES("ds${0..1}.torder_${0..2}"), TABLESTRATEGY(TYPE=STANDARD,SHARDINGCOLUMN=orderid,SHARDINGALGORITHM=torderinline), KEYGENERATESTRATEGY(COLUMN=orderid,KEYGENERATOR=snowflakekeygenerator) ); ``` `DATANODES` specifies the data nodes of shard tables. `TABLESTRATEGY` specifies the table strategy, among which `SHARDINGALGORITHM` uses created sharding algorithm `torderinline`; `KEYGENERATESTRATEGY` specifies the primary key generation strategy of the table. Skip this configuration if primary key generation is not required. 2.`torderitem` ``` CREATE SHARDING TABLE RULE torderitem ( DATANODES("ds${0..1}.torderitem${0..2}"), TABLESTRATEGY(TYPE=STANDARD,SHARDINGCOLUMN=orderid,SHARDINGALGORITHM=torderitem_inline), KEYGENERATESTRATEGY(COLUMN=orderitemid,KEYGENERATOR=snowflakekey_generator) ); ``` 3.Query sharding rules ``` mysql> SHOW SHARDING TABLE RULES\G; row * table: t_order actualdatanodes: ds${0..1}.torder_${0..2} actualdatasources: databasestrategytype: STANDARD databaseshardingcolumn: user_id databaseshardingalgorithm_type: inline databaseshardingalgorithmprops: algorithm-expression=ds${user_id % 2} tablestrategytype: STANDARD tableshardingcolumn: order_id tableshardingalgorithm_type: inline tableshardingalgorithmprops: algorithm-expression=torder${orderid % 3} keygeneratecolumn: order_id keygeneratortype: snowflake keygeneratorprops: row * table: torderitem actualdatanodes: ds${0..1}.torderitem${0..2} actualdatasources: databasestrategytype: STANDARD databaseshardingcolumn: user_id databaseshardingalgorithm_type: inline databaseshardingalgorithmprops: algorithm-expression=ds${user_id % 2} tablestrategytype: STANDARD tableshardingcolumn: order_id tableshardingalgorithm_type: inline tableshardingalgorithmprops: algorithm-expression=torderitem${order_id % 3} keygeneratecolumn: orderitemid keygeneratortype: snowflake keygeneratorprops: 2 rows in set (0.00 sec) ``` So far, the sharding rules for `torder` and `torder_item` have been configured. A bit complicated? Well, you can also skip the steps of creating the primary key generator, sharding algorithm, and default strategy, and complete the sharding rules in one step. Let's see how to make it easier. Syntax Now, if we have to add a shard table `torderdetail`, we can create sharding rules as follows: ``` CREATE SHARDING TABLE RULE torderdetail ( DATANODES("ds${0..1}.torderdetail${0..1}"), DATABASESTRATEGY(TYPE=STANDARD,SHARDINGCOLUMN=userid,SHARDINGALGORITHM(TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="ds${userid % 2}")))), TABLESTRATEGY(TYPE=STANDARD,SHARDINGCOLUMN=orderid,SHARDINGALGORITHM(TYPE(NAME=INLINE,PROPERTIES("algorithm-expression"="torderdetail${orderid % 3}")))), KEYGENERATESTRATEGY(COLUMN=detail_id,TYPE(NAME=snowflake)) ); ``` Note: The above statement specified database sharding strategy, table strategy, and primary key generation strategy, but it didnt use existing algorithms. Therefore, the DistSQL engine automatically uses the input expression to create an algorithm for the sharding rules of `torderdetail`. Now the primary key generator, sharding algorithm, and sharding rules are as follows:

key generator ``` mysql> SHOW SHARDING KEY GENERATORS; +--+--+-+ | name | type | props | +--+--+-+ | snowflakekeygenerator | snowflake | {} | | torderdetail_snowflake | snowflake | {} | +--+--+-+ 2 rows in set (0.00 sec) ``` 2.Sharding algorithm ``` mysql> SHOW SHARDING ALGORITHMS; +--+--+--+ | name | type | props | +--+--+--+ | databaseinline | inline | algorithm-expression=ds${user_id % 2} | | torderinline | inline | algorithm-expression=torder${order_id % 3} | | torderiteminline | inline | algorithm-expression=torderitem${order_id % 3} | | torderdetaildatabaseinline | inline | algorithm-expression=ds${userid % 2} | | torderdetailtableinline | inline | algorithm-expression=torderdetail${orderid % 3} | +--+--+--+ 5 rows in set (0.00 sec) ``` 3.Sharding rules ``` mysql> SHOW SHARDING TABLE RULES\G; row * table: t_order actualdatanodes: ds${0..1}.torder_${0..2} actualdatasources: databasestrategytype: STANDARD databaseshardingcolumn: user_id databaseshardingalgorithm_type: inline databaseshardingalgorithmprops: algorithm-expression=ds${user_id % 2} tablestrategytype: STANDARD tableshardingcolumn: order_id tableshardingalgorithm_type: inline tableshardingalgorithmprops: algorithm-expression=torder${orderid % 3} keygeneratecolumn: order_id keygeneratortype: snowflake keygeneratorprops: row * table: torderitem actualdatanodes: ds${0..1}.torderitem${0..2} actualdatasources: databasestrategytype: STANDARD databaseshardingcolumn: user_id databaseshardingalgorithm_type: inline databaseshardingalgorithmprops: algorithm-expression=ds${user_id % 2} tablestrategytype: STANDARD tableshardingcolumn: order_id tableshardingalgorithm_type: inline tableshardingalgorithmprops: algorithm-expression=torderitem${order_id % 3} keygeneratecolumn: orderitemid keygeneratortype: snowflake keygeneratorprops: row * table: torderdetail actualdatanodes: ds${0..1}.torderdetail${0..1} actualdatasources: databasestrategytype: STANDARD databaseshardingcolumn: user_id databaseshardingalgorithm_type: inline databaseshardingalgorithmprops: algorithm-expression=ds${user_id % 2} tablestrategytype: STANDARD tableshardingcolumn: order_id tableshardingalgorithm_type: inline tableshardingalgorithmprops: algorithm-expression=torderdetail${order_id % 3} keygeneratecolumn: detail_id keygeneratortype: snowflake keygeneratorprops: 3 rows in set (0.01 sec) ``` Note: In the `CREATE SHARDING TABLE RULE` statement, `DATABASESTRATEGY`, `TABLESTRATEGY`, and `KEYGENERATESTRATEGY` can all reuse existing algorithms. Alternatively, they can be defined quickly through syntax. The difference is that additional algorithm objects are created. Users can use it flexibly based on scenarios. After the configuration verification rules are created, you can verify them in the following ways: Checking node distribution DistSQL provides `SHOW SHARDING TABLE NODES` for checking node distribution and users can quickly learn the distribution of shard tables. We can see the node distribution of the shard table is consistent with what is described in the requirement. SQL Preview Previewing SQL is also an easy way to verify configurations. Its syntax is `PREVIEW SQL`: 1.Query with no shard key with all routes 2.Specify `user_id` to query with a single database route 3.Specify `userid` and `orderid` with a single table route Single-table routes scan the least shard tables and offer the highest efficiency. During the system maintenance, algorithms or storage resources that are no longer in use may need to be released, or resources that need to be released may have been referenced and cannot be deleted. The following DistSQL can solve these problems. Query unused resources 1.Syntax: `SHOW UNUSED RESOURCES` 2.Sample: Query unused primary key generator 1.Syntax: `SHOW UNUSED SHARDING KEY GENERATORS` 2.Sample: Query unused sharding algorithm 1.Syntax: `SHOW UNUSED SHARDING ALGORITHMS` 2.Sample: Query rules that use the target storage resources 1.Syntax: `SHOW RULES USED RESOURCE` 2.Sample: All rules that use the resource can be queried, not limited to the `Sharding Rule`. Query sharding rules that use the target primary key generator 1.Syntax: `SHOW SHARDING TABLE RULES USED KEY GENERATOR` 2.Sample: Query sharding rules that use the target algorithm 1.Syntax: `SHOW SHARDING TABLE RULES USED ALGORITHM` 2.Sample: This post takes the data sharding scenario as an example to introduce s applications and methods. DistSQL provides flexible syntax to help simplify operations. In addition to the `INLINE` algorithm, DistSQL supports standard sharding, compound sharding, Hint sharding, and custom sharding algorithms. More examples will be covered in the coming future. If you have any questions or suggestions about , please feel free to post them on the GitHub Issue list. [ShardingSphere Slack ](https://join.slack.com/t/apacheshardingsphere/shared_invite/zt-sbdde7ie-SjDqo9~I4rYcR18bq0SYTg) [Concept INLINE Expression ](https://shardingsphere.apache.org/document/current/en/features/sharding/concept/inline-expression/) [Built-in Sharding Algorithm ](https://shardingsphere.apache.org/document/current/en/user-manual/common-config/builtin-algorithm/sharding/) [User Manual: DistSQL ](https://shardingsphere.apache.org/document/current/en/user-manual/shardingsphere-proxy/distsql/syntax/) Jiang Longtao Middleware R&D Engineer &