7.5 Channels (code)

About

This tutorial presents the code implementation for subchapter "Fixed 'MySQL source - MDS' replication"

Code example

Example code at github repository: https://github.com/MuchTest/MySqlDbSystemExample3

The code will implement (in two parts):

First part:

  • creating a VCN and compartment

  • deploying an OCI instance and provisioning MySQL service

  • creating a MySQL DB System

  • creating an object storage(bucket)

After setting up the /root/.oci/config for object storage, and performing the GTID purging on MDS target, you can create the channel:

Second part :

  • creating the channel by using "terraform apply target"

Changes implemented on the code:

  1. "remote.tf" - MySQL-shell snapd installation has been replaced by installing MySQL-Shell from official repository for enabling Javascript mode (apparently,

root@deploymentmachine:/home# diff channel_replica/remote.tf bucket_test/remote.tf
18,19c18,21
<               "sudo apt install -y snapd",
<               "sudo snap install mysql-shell"]
---
>               "sudo wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell_8.0.23-1ubuntu20.04_amd64.deb",
>               "sudo dpkg -i mysql-shell_8.0.23-1ubuntu20.04_amd64.deb",
>               "sudo apt update"
>               ]
34d35
<
root@deploymentmachine:/home#
}

2. "mysql.yml" - provided root password

root@deploymentmachine:/home#  diff channel_replica/mysql.yml bucket_test/mysql.yml
72a73,76
>     - name: Password for root login
>       command: /usr/bin/mysql -uroot -e "ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'abc123!';"
>       become: yes
>
74c78
<       command: /usr/bin/mysql -uroot -e "flush privileges;"
---
>       command: /usr/bin/mysql -uroot -pabc123! -e "flush privileges;"
root@deploymentmachine:/home# 

3. "channel.tf" will not be called when deploying the environment. The creation of channel will happen when the dumping/loading data and GTID purging are correctly implemented.

4. "variables.tf" - variables added for configuring the object storage (bucket):

root@deploymentmachine:/home/bucket_test# more variables.tf | grep -A2 bucket
## for bucket
variable  "name_bucket"{
  default = "mdsbucket"
}

variable "bucket_namespace" {
  default = " " ## add here your namespace
}

n.b: You need to find the ID of the bucket and add it to the variable bucket_namespace

You can find the namespace with command "oci os ns get"

root@deploymentmachine:/home# export OCI_CLI_SUPPRESS_FILE_PERMISSIONS_WARNING=True
root@deploymentmachine:/home# oci os ns get
{
  "data": "some info here"
}

and of course, create_bucket.tf for creation of the bucket

root@deploymentmachine:/home/bucket_test# more create_bucket.tf
resource "oci_objectstorage_bucket" "mds_bucket" {

    compartment_id = oci_identity_compartment.MySqlOciCompartment.id
    name = var.name_bucket
    namespace = var.bucket_namespace
    storage_tier = "Standard"
}

# resource "oci_objectstorage_object" "test_object" {

#   bucket = oci_objectstorage_bucket.mds_bucket.name
#    namespace = var.bucket_namespace

#    object = var.bucket_object

#    storage_tier = "Standard"
# }

Folder's content:

root@deploymentmachine:/home/bucket_test# tree .
.
├── ansible.cfg
├── channel
│   └── create_channel.tf
├── compartment.tf
├── create_bucket.tf
├── create_mysql.tf
├── data.tf
├── dhcp_opt.tf
├── instance.tf
├── int_gateway.tf
├── my.cnf
├── mysql.yml
├── output.tf
├── provider.tf
├── remote.tf
├── replication.yml
├── route.tf
├── security_list.tf
├── subnet.tf
├── variables.tf
└── vcn.tf

1 directory, 20 files

First Part

Perform the usual terraform commands: terraform init, terraform plan, terraform apply

After the "terraform apply" you will have created/launched following:

  • a VCN and a compartment

  • an OCI instance on which we provisioned MySQL service (mysqlshellinstance)

  • a MySQL DB System

  • an object storage(bucket)

The created Object storage in OCI UI:

Setting up the /root/.oci/config for object storage

You can find the tutorial, step-by-step, at: Install and Configure OCI CLI

Keep in mind, that now you make the changes for the compartment where the MDS, MySQL source and Object bucket are located. This configuration file /root/.oci/config must exist on the instance that can access the MDS (in our case, it's the instance "MySqlShellInsance"

Performing the GTID purging

a) Dumping data from MySQL source into Bucket

Log in to mysqlshellinstance, and create a database:

root@deploymentmachine:/home/bucket_test# instanceip=`terraform output MySqlSourceIP | sed 's/"//g'`
root@deploymentmachine:/home/bucket_test#
root@deploymentmachine:/home/bucket_test# ssh ubuntu@$instanceip
Welcome to Ubuntu 20.04.1 LTS (GNU/Linux 5.4.0-1035-oracle x86_64)
[.... snip ....]
ubuntu@mysqlshellinstance:~$ sudo -i
root@mysqlshellinstance:~# cd /home
root@mysqlshellinstance:/home# mysql -uroot -pabc123!

[.... snip ....] 

mysql> create database hehe;
Query OK, 1 row affected (0.00 sec)

mysql> create table hehe.hehehe (name varchar(20), firstname varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into hehe.hehehe (name, firstname) values ('Foster', 'Zack');
Query OK, 1 row affected (0.01 sec)

mysql>  select * from  hehe.hehehe;
+--------+-----------+
| name   | firstname |
+--------+-----------+
| Foster | Zack      |
+--------+-----------+
1 row in set (0.00 sec)

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| hehe               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql>

Dump data into bucket from mysql-shell:

root@mysqlshellinstance:/home# mysqlsh -uroot -pabc123!
Please provide the password for 'root@localhost': *******
Save password for 'root@localhost'? [Y]es/[N]o/Ne[v]er (default No): N
MySQL Shell 8.0.23
[... snip.... ]
MySQL  localhost:33060+ ssl  JS > util.dumpInstance("mdsobject", {osBucketName: "mdsbucket", osNamespace: "add here namespace", threads: 4, ocimds: true, compatibility: ["strip_restricted_grants"]})
Acquiring global read lock
Global read lock acquired
Gathering information - done
All transactions have been started
Locking instance for backup
Global read lock has been released
Checking for compatibility with MySQL Database Service 8.0.23
NOTE: User 'debian-sys-maint'@'localhost' had restricted privileges (AUDIT_ADMIN, BACKUP_ADMIN, BINLOG_ADMIN, BINLOG_ENCRYPTION_ADMIN, CLONE_ADMIN, CREATE TABLESPACE, ENCRYPTION_KEY_ADMIN, FILE, FLUSH_OPTIMIZER_COSTS, FLUSH_STATUS, FLUSH_TABLES, FLUSH_USER_RESOURCES, GROUP_REPLICATION_ADMIN, INNODB_REDO_LOG_ARCHIVE, INNODB_REDO_LOG_ENABLE, PERSIST_RO_VARIABLES_ADMIN, RELOAD, REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SERVICE_CONNECTION_ADMIN, SESSION_VARIABLES_ADMIN, SET_USER_ID, SHOW_ROUTINE, SHUTDOWN, SUPER, SYSTEM_USER, SYSTEM_VARIABLES_ADMIN, TABLE_ENCRYPTION_ADMIN) removed
NOTE: User 'root'@'localhost' had restricted privileges (AUDIT_ADMIN, BACKUP_ADMIN, BINLOG_ADMIN, BINLOG_ENCRYPTION_ADMIN, CLONE_ADMIN, CREATE TABLESPACE, ENCRYPTION_KEY_ADMIN, FILE, FLUSH_OPTIMIZER_COSTS, FLUSH_STATUS, FLUSH_TABLES, FLUSH_USER_RESOURCES, GROUP_REPLICATION_ADMIN, INNODB_REDO_LOG_ARCHIVE, INNODB_REDO_LOG_ENABLE, PERSIST_RO_VARIABLES_ADMIN, PROXY, RELOAD, REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SERVICE_CONNECTION_ADMIN, SESSION_VARIABLES_ADMIN, SET_USER_ID, SHOW_ROUTINE, SHUTDOWN, SUPER, SYSTEM_USER, SYSTEM_VARIABLES_ADMIN, TABLE_ENCRYPTION_ADMIN) removed
NOTE: Database hehe had unsupported ENCRYPTION option commented out
Compatibility issues with MySQL Database Service 8.0.23 were found and repaired. Please review the changes made before loading them.
Writing global DDL files
Writing users DDL
Writing DDL for schema `hehe`
Writing DDL for table `hehe`.`hehehe`
Preparing data dump for table `hehe`.`hehehe`
NOTE: Could not select a column to be used as an index for table `hehe`.`hehehe`. Chunking has been disabled for this table, data will be dumped to a single file.
Data dump for table `hehe`.`hehehe` will be written to 1 file
Running data dump using 4 threads.
NOTE: Progress information uses estimated values and may not be accurate.
1 thds dumping - ?% (1 rows / ?), 0.00 rows/s, 10.00 B/s uncompressed, 0.00 B/s compressed
Duration: 00:00:01s
Schemas dumped: 1
Tables dumped: 1
Uncompressed data size: 12 bytes
Compressed data size: 0 bytes
Compression ratio: 12.0
Rows written: 1
Bytes written: 0 bytes
Average uncompressed throughput: 10.90 B/s
Average compressed throughput: 0.00 B/s
 MySQL  localhost:33060+ ssl  JS > \q
Bye!
root@mysqlshellinstance:/home#

Now, the bucket has the following "mdsobject" object with contents:

Save file @.json on the mysqlshellinstance:

root@mysqlshellinstance:/home# cat > @.json << EOF
> {
>     "dumper": "mysqlsh Ver 8.0.23 for Linux on x86_64 - for MySQL 8.0.23 (MySQL Community Server (GPL))",
>     "version": "1.0.2",
>     "origin": "dumpInstance",
>     "schemas": [
>         "hehe"
>     ],
>     "basenames": {
>         "hehe": "hehe"
>     },
>     "users": [
>         "'debian-sys-maint'@'localhost'",
>         "'replicauser'@'%'",
>         "'root'@'localhost'"
>     ],
>     "defaultCharacterSet": "utf8mb4",
>     "tzUtc": true,
>     "bytesPerChunk": 64000000,
>     "user": "root",
>     "hostname": "mysqlshellinstance",
>     "server": "mysqlshellinstance",
>     "serverVersion": "8.0.23-0ubuntu0.20.04.1",
>     "gtidExecuted": "1beaf71c-8b06-11eb-898a-00001702dfe1:1-10",
>     "gtidExecutedInconsistent": false,
>     "consistent": true,
>     "mdsCompatibility": true,
>     "begin": "2021-03-22 12:30:22"
> }
> EOF

b) Loading data from Bucket into MySQL DB system

root@mysqlshellinstance:/home# mysqlsh -uusermds -h10.0.1.4 -pABCabc123$%
MySQL Shell 8.0.23
[... snip ... ]
 MySQL  10.0.1.4:33060+ ssl  JS >
 MySQL  10.0.1.4:33060+ ssl  JS > util.loadDump("mdsobject", {osBucketName: "mdsbucket", osNamespace: "add here namespace", threads: 4})
Loading DDL and Data from OCI ObjectStorage bucket=mdsbucket, prefix='mdsobject' using 4 threads.
Opening dump...
Target is MySQL 8.0.23-u2-cloud (MySQL Database Service). Dump was produced from MySQL 8.0.23-0ubuntu0.20.04.1
Fetching dump data from remote location...
Fetching 1 table metadata files for schema `hehe`...
Checking for pre-existing objects...
Executing common preamble SQL
Executing DDL script for schema `hehe`
[Worker002] Executing DDL script for `hehe`.`hehehe`
[Worker001] hehe@hehehe.tsv.zst: Records: 1  Deleted: 0  Skipped: 0  Warnings: 0
Executing common postamble SQL

1 chunks (1 rows, 12 bytes) for 1 tables in 1 schemas were loaded in 1 sec (avg throughput 12.00 B/s)
0 warnings were reported during the load.
 MySQL  10.0.1.4:33060+ ssl  JS >

Check if data is loaded, and perform the GTID purging:

root@mysqlshellinstance:/home# mysql -uusermds -h10.0.1.4 -pABCabc123$%

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| hehe               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.01 sec)

mysql>
mysql> call sys.set_gtid_purged("1beaf71c-8b06-11eb-898a-00001702dfe1:1-10")
    -> ;
Query OK, 0 rows affected (0.02 sec)
mysql> show global variables like 'GTID%';
+----------------------------------+-------------------------------------------------------------------------------------+
| Variable_name                    | Value                                                                               |
+----------------------------------+-------------------------------------------------------------------------------------+
| gtid_executed                    | 1beaf71c-8b06-11eb-898a-00001702dfe1:1-10,76a2b021-8b06-11eb-839e-020017069921:1-3 |
| gtid_executed_compression_period | 0                                                                                   |
| gtid_mode                        | ON                                                                                  |
| gtid_owned                       |                                                                                     |
| gtid_purged                      | 1beaf71c-8b06-11eb-898a-00001702dfe1:1-10                                           |
+----------------------------------+-------------------------------------------------------------------------------------+
5 rows in set (0.00 sec)

mysql>
mysql> exit
Bye
root@mysqlshellinstance:/home#
root@mysqlshellinstance:/home# exit
logout
ubuntu@mysqlshellinstance:~$ exit
logout
Connection to 130.61.186.185 closed.
root@deploymentmachine:/home/bucket_test#

Second part

Time to deploy the channel:

root@deploymentmachine:/home/bucket_test# 
root@deploymentmachine:/home/bucket_test# cp channel/create_channel.tf .
root@deploymentmachine:/home/bucket_test# 
root@deploymentmachine:/home/bucket_test# terraform plan -target oci_mysql_channel.MySqlOciChannel
[.... snip .....] 
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # oci_mysql_channel.MySqlOciChannel will be created
  + resource "oci_mysql_channel" "MySqlOciChannel" {
      + compartment_id    = "ocid1.compartment.oc1..a"
      + defined_tags      = (known after apply)
      + description       = (known after apply)
      + display_name      = (known after apply)
      + freeform_tags     = (known after apply)
      + id                = (known after apply)
      + is_enabled        = true
      + lifecycle_details = (known after apply)
      + state             = (known after apply)
      + time_created      = (known after apply)
      + time_updated      = (known after apply)

      + source {
          + hostname    = "mysqlshellinstance.mysqloci.mysqlocivcn.oraclevcn.com"
          + password    = (sensitive value)
          + port        = 3307
          + source_type = "MYSQL"
          + ssl_mode    = "DISABLED"
          + username    = "replicauser"

          + ssl_ca_certificate {
              + certificate_type = (known after apply)
              + contents         = (known after apply)
            }
        }

      + target {
          + applier_username = (known after apply)
          + channel_name     = (known after apply)
          + db_system_id     = "ocid1.mysqldbsystem.oc1.eu-frankfurt-1.aaa"
          + target_type      = "DBSYSTEM"
        }
    }

If no errors, apply changes:

root@deploymentmachine:/home/bucket_test#  terraform apply -target oci_mysql_channel.MySqlOciChannel

[ ... snip ... ]

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

oci_mysql_channel.MySqlOciChannel: Creating...

[ ... snip ... ]

Check from UI, if channel is active

Go back to mysqlshellinstance, and check status of the slave, via MySQL Client:

root@mysqlshellinstance:~# mysql -uusermds -h10.0.1.4 -pABCabc123$%
[ .... snip .... ]

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: mysqlshellinstance.mysqloci.mysqlocivcn.oraclevcn.com
                  Master_User: replicauser
                  Master_Port: 3307
                Connect_Retry: 60
              Master_Log_File: binlog.000004
          Read_Master_Log_Pos: 2991
               Relay_Log_File: relay-log-replication_channel.000002
                Relay_Log_Pos: 409
        Relay_Master_Log_File: binlog.000004
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
            
       [ .... snip .... ]
       
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0

      [ .... snip .... ]
 
                  Master_UUID: 1beaf71c-8b06-11eb-898a-00001702dfe1
             Master_Info_File: mysql.slave_master_info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 0
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
   [ .... snip .... ]
            Executed_Gtid_Set: 1beaf71c-8b06-11eb-898a-00001702dfe1:1-10,
76a2b021-8b06-11eb-839e-020017069921:1-3
                Auto_Position: 1
         Replicate_Rewrite_DB:
                 Channel_Name: replication_channel
           Master_TLS_Version: TLSv1.2,TLSv1.3
       Master_public_key_path:
        Get_master_public_key: 1
            Network_Namespace: mysql
1 row in set, 1 warning (0.00 sec)

Check replication

Now, access MySQL source via MySQL client, and create another database:

root@mysqlshellinstance:~# mysql -uroot -pabc123!
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 21
Server version: 8.0.23-0ubuntu0.20.04.1 (Ubuntu)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> create database testingcode;
Query OK, 1 row affected (0.01 sec)

mysql> create table testingcode.hehehe (name varchar(20), firstname varchar(20));
Query OK, 0 rows affected (0.02 sec)

mysql> insert into testingcode.hehehe (name, firstname) values ('Foster', 'Zack');
Query OK, 1 row affected (0.01 sec)

mysql>

... and access once again MDS to see if replication was possible:

root@mysqlshellinstance:~# mysql -uusermds -h10.0.1.4 -pABCabc123$%
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 32
Server version: 8.0.23-u2-cloud MySQL Enterprise - Cloud

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| hehe               |
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| testingcode        |
+--------------------+
6 rows in set (0.00 sec)

mysql> use testingcode;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------------+
| Tables_in_testingcode |
+-----------------------+
| hehehe                |
+-----------------------+
1 row in set (0.00 sec)

mysql> select * from testingcode.hehehe;
+--------+-----------+
| name   | firstname |
+--------+-----------+
| Foster | Zack      |
+--------+-----------+
1 row in set (0.00 sec)

mysql>

Destroy resources

Before destroying the resources, you need to empty the bucket, otherwise you may end up with this kind of error:

Error: 409-BucketNotEmpty
Service: ObjectStorageBucket
Error Message: Bucket named 'mdsbucket' is not empty. Delete all object versions first.
OPC request ID: ////
Suggestion: The resource is in a conflicted state. Please retry again or contact support for help with service: ObjectStorageBucket

Delete pre-authenticated requests:

For deleting pre-authenticated requests from mdsbucket by using the OCI CLI, use the command line:

for idz in `oci os preauth-request list -bn mdsbucket | grep id | awk '{print $2}' | sed 's/",//g' | sed 's/"//g'`; \
do echo y | oci os preauth-request delete  -bn mdsbucket --par-id $idz  ; \
done

... and delete the object's contents:

Now, you can apply "terraform destroy"

Code for an architecture with Instance in a public subnet, and MDS in a private subnet, at following github repository: https://github.com/MuchTest/ExampleMySqlDbAndInstance

Fini!

Last updated