Quantcast
Channel: Planet MySQL
Viewing all 18830 articles
Browse latest View live

Why Database Schema Optimization Matters

$
0
0
Schema Optimization

If you have been around MySQL for any length of time, you are probably aware that choosing the correct data types and optimizing your schema are actually important tasks.  A few years back at Percona Live 2016, I gave an introductory talk on schema review and optimization. Here’s the video:

 

I was thinking about that talk in the context of some of my current clients.  Though I had worked on extremely large database deployments during my earlier tenure at Percona, it was often more of an outlier.  Now, working as a Technical Account Manager with our largest clients, it is much more common.

The Fundamental Problem

I’d like to expand my thoughts on the “choosing the smallest data type you can” principle from my 2016 slides through the lens of a few of my 2019 clients.  I gave an example of two copies of the same table (a simple 4 column, 3 index table with ~4 million rows), one using a bigint for the primary key and one using a regular unsigned int for the primary key:

[root@sample-host plive_2016]# ls -alh action*ibd
-rw-rw---- 1 mysql mysql 908M Apr 7 16:22 action_bigint.ibd 
-rw-rw---- 1 mysql mysql 636M Apr 7 16:23 action.ibd

In this example, there was almost a 30% space savings associated with using the smaller data type.  Obviously, at the scale of 1GB of space, this is trivial. One comment I made during the talk references the adage “storage is cheap”.  While this can be true at a certain scale, I’m seeing this thinking break down more frequently with my largest clients.

The Problem Magnified at Scale

As an illustration, one of my clients is running roughly 10,000 Percona Server instances in their sharded deployment.  These servers are running on bare metal with above-average hardware (for performance concerns). While that sounds like a lot of servers (and it definitely is), you also have to take into consideration other operational concerns such as backups.  For the sake of some easier math, let’s assume the following:

  • 5 servers/shard
  • 500G data directory
  • 5 backups of each shard (various time ranges such as daily, weekly, monthly)

Using those numbers as an estimate, one would be looking at roughly the following for space:

  • ~4.7 petabytes storage for running instances (SSD)
  • ~6 petabytes storage for backups (HDD)

The Business Impact on Large Deployments

Suddenly, at that scale, the 30% space that seemed trivial in my example seems a bit more important.  Let’s run some numbers based on the current $/TB pricing of SSD and spinning HDD with the 30% reduction in space:

  • SSD Savings ~ $140,000
    • $100/TB Cost
    • 30% of 4.7PB = 1.4PB
  • HDD Savings ~ $46,000
    • $25/TB Cost
    • 30% of 6PB = 1.8PB

Saving 3 petabytes of storage would reduce the raw storage costs by nearly $200,000.  On top of the actual capital costs of 3PB of storage, you have to consider server count, power, and maintenance (among others) which would increase this cost significantly.  Clearly, this is just a theoretical example of the potential impact a small mistake like picking the wrong data type can have on the overall infrastructure cost at scale. Generally, by the time a company reaches this scale, these sorts of optimizations have already been made and we need to start looking deeper and more creatively at other alternatives.

While this is definitely an oversimplification of calculating storage costs based on raw hardware prices, it does beg the question: even though it may not seem important now, why not ensure your schema is optimized before it becomes an expensive problem to fix!

For a more holistic view of how optimizations such as this one can save you money, check out our Database Management Savings Calculator or reach out to us for a more thorough review.


Read the White Paper: Tungsten Clustering for MySQL, MariaDB & Percona Server Databases

$
0
0

We’re happy to announce that our white paper ‘Tungsten Clustering – Benefits & Configurations’ for MySQL, MariaDB and Percona Server is available to read on our website.

Tungsten Clustering is a one-of-a-kind software solution that provides clustering, disaster recovery and high availability for MySQL, MariaDB & Percona Server databases.

It allows enterprises running business-critical database applications to cost-effectively achieve continuous operations on a global scale with:

  • Commercial-grade high availability (HA)
  • Geographically redundant disaster recovery (DR)
  • Global operations with geographically distributed multi-master

Read the White Paper
Amongst other things, Tungsten Clustering makes it simple to:

  • Create database clusters in the cloud or in your private data centers
  • Keep the data available even when systems fail
  • Free you up to focus on your business and applications

This white paper provides a technical overview of Tungsten Clustering covering its key benefits as well as outlining some key configurations.

More specifically, the topics included in this white paper include:

  • Introduction to Tungsten Clustering
  • Key Benefits
  • Components
    • Tungsten Connector
    • Tungsten Manager
    • Tungsten Replicator
    • Tungsten Dashboard
  • Primary / DR Composite Clustering
  • Multi-Site Multi-Master Composite Clustering
  • Single Site Solutions

Some of Tungsten Clustering’s key features and benefits for MySQL, MariaDB & Percona Server include:

  • Continuous Operations
  • Zero Downtime
  • Geo-Scale
  • Hybrid-Cloud and Multi-Cloud
  • Intelligent Proxy
  • Most Advanced Replication
  • Full Support, No Application Changes

Read the White Paper

As one of our customers put it: “Tungsten Clustering has allowed us to deploy clusters in the Amazon Cloud quickly, which is key for our rapidly growing company. In addition, Tungsten Clustering is a key component in allowing us to meet our uptime SLA. Perhaps the most important item is the support we receive from Continuent, which I am pleased to say, responds quickly and resolves all issues (including self-inflicted!), and accepts feedback for future enhancements.”

To find out all there is to know about Tungsten Clustering, please read the white paper.

Alternatively, feel free to contact us for any questions.

MySQL Check Constraints to the Rescue

$
0
0

   arrow

You as a MySQL administrator/developer are really excited about cloning in MySQL 8.0.17.  You are reading all the recent blogs. You know that quickly getting a replica up and running is quite important to your dev team.

Besides, ‘cloning’ reminds you of the old classic film ‘Sleeper’ where the actors clone a new leader from the dead leader’s nose. 

Thinking of all this puts you in great spirits. Moving from MySQL 5.7 to MySQL 8.0 is high on your agenda. 

Suddenly, the CEO walks up to your desk. “We lost millions in sales last quarter,” he yells. “It’s your fault. We sold all of our items at the discounted price rather than the actual price. You need to fix this today if not sooner.” 

With that, the CEO reminds you of another reason to move to MySQL 8.0 : check constraints, which came out in 8.0.16. 

You know that ensuring that data is accurate is a big task. Someone may have put logic to keep prices in check in the code, but who knows? It is better to add this logic to the database. Constraints in a database will be more permanent than if constraints live in application code that changes frequently. In the database, there is just one place for constraints and that is on the object layer.

You get to work. You design three check constraints to ensure that your CEO is happy and you will never sell products at the wrong price again. You notice that in the old product table, there were no constraints on the price columns in the table.  The values for the ‘price’ column were often lower than the ‘sales_price’ column.

The table constraint below sets three constraints. The last constraint on the table product below in bold ensures that the regular price is always higher than the sales price. The error that occurs below on adding a new product or updating an existing product shows that the third check constraint is being applied:

CREATE TABLE product
(
product_no INTEGER,
name TEXT,
price NUMERIC CHECK (price > 0),
sale_price NUMERIC CHECK (sale_price > 0),
CHECK (price > sale_price)
);

mysql> INSERT INTO product VALUES (1, ‘teeth-cleaning-gum’, 10, 10);

ERROR 3819 (HY000): Check constraint ‘products_chk_3’ is violated.

 

The CEO wanders back asking to see your work to prevent another financial loss. After you show him your work, he looks more positive. His only comment is ‘when is your team moving to MySQL 8.0?’  You nod, saying that with all the improvements to the MySQL code the time to move to MySQL 8.0 is now.

Upgrading from MySQL 5.7 to MySQL 8.0 Part I

$
0
0
MySQL 8.0 has been the fastest in uptake of any version of MySQL.  But there are still a few of your still running 5.7.  To help you get from 5.7 to 8.0 you can use the new MySQL Shell or mysql.  The mysqlsh program has a built in upgrade checker to make sure you have an easy upgrade and to warn you of any potential problems before your smack into them.

The first step is to install mysqlsh and it can be as simple as using the MySQL apt repo and then running sudo apt-get install mysql-shell. See A Quick Guide to Using the MySQL Apt Repo.

Second is connecting with the new shell. Now something to note is that you have to specify the port for the standard protocol as the new shell wants to default to using the new protocol's port at 33060.  Simply specify the root account, the host, and that 3306 port.

Next run the upgrade checker utility with util.checkForServerUpgrade("root@localhost:3306")

And the upgrade checker will tell what, if anything needs to be updated. The example below is kind of boring as it does not have any major problems to solve. But it does show how to check what your 5.7 needs before your upgrade.

$ mysqlsh root@localhost:3306
Please provide the password for 'root@localhost:3306': ******
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):
MySQL Shell 8.0.17

Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its affiliates.
Other names may be trademarks of their respective owners.

Type '\help' or '\?' for help; '\quit' to exit.
Creating a session to 'root@localhost:3306'
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 9
Server version: 5.7.27 MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
MySQL localhost:3306 ssl JS>util.checkForServerUpgrade("root@localhost:3306")
Please provide the password for 'root@localhost:3306': ******
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No):

The MySQL server at localhost:3306, version 5.7.27 - MySQL Community Server
(GPL), will now be checked for compatibility issues for upgrade to MySQL
8.0.17...

1) Usage of old temporal type
  No issues found

2) Usage of db objects with names conflicting with reserved keywords in 8.0
  No issues found

3) Usage of utf8mb3 charset
  No issues found

4) Table names in the mysql schema conflicting with new tables in 8.0
  No issues found

5) Partitioned tables using engines with non native partitioning
  No issues found

6) Foreign key constraint names longer than 64 characters
  No issues found

7) Usage of obsolete MAXDB sql_mode flag
  No issues found

8) Usage of obsolete sql_mode flags
  No issues found

9) ENUM/SET column definitions containing elements longer than 255 characters
  No issues found

10) Usage of partitioned tables in shared tablespaces
  No issues found

11) Circular directory references in tablespace data file paths
  No issues found

12) Usage of removed functions
  No issues found

13) Usage of removed GROUP BY ASC/DESC syntax
  No issues found

14) Removed system variables for error logging to the system log configuration
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-13.html#mysqld-8-0-13-logging

15) Removed system variables
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/added-deprecated-removed.html#optvars-removed

16) System variables with new default values
  To run this check requires full path to MySQL server configuration file to be specified at 'configPath' key of options dictionary
  More information:
    https://mysqlserverteam.com/new-defaults-in-mysql-8-0/

17) Schema inconsistencies resulting from file removal or corruption
  No issues found

18) Issues reported by 'check table x for upgrade' command
  No issues found

19) New default authentication plugin considerations
  Warning: The new default authentication plugin 'caching_sha2_password' offers
    more secure password hashing than previously used 'mysql_native_password'
    (and consequent improved client connection authentication). However, it also
    has compatibility implications that may affect existing MySQL installations.
    If your MySQL installation must serve pre-8.0 clients and you encounter
    compatibility issues after upgrading, the simplest way to address those
    issues is to reconfigure the server to revert to the previous default
    authentication plugin (mysql_native_password). For example, use these lines
    in the server option file:
   
    [mysqld]
    default_authentication_plugin=mysql_native_password
   
    However, the setting should be viewed as temporary, not as a long term or
    permanent solution, because it causes new accounts created with the setting
    in effect to forego the improved authentication security.
    If you are using replication please take time to understand how the
    authentication plugin changes may impact you.
  More information:
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-compatibility-issues
    https://dev.mysql.com/doc/refman/8.0/en/upgrading-from-previous-series.html#upgrade-caching-sha2-password-replication

Errors:   0
Warnings: 1
Notices:  0

No fatal errors were found that would prevent an upgrade, but some potential issues were detected. Please ensure that the reported issues are not significant before upgrading.

Next Time 


Next time I will look at solving some of the more common errors.




Where is the MySQL team this and next week?!

$
0
0

This week you can find our MySQL & MySQL Community experts at following shows:

  • db tech showcase, Tokyo, Japan, September 25-27, 2019
    • MySQL team as Silver sponsor will have a booth in the expo area and in total 5 speaking slots related to MySQL as follows: 
      • Two User Case Studies of MySQL
      • Two Technical Sessions by MySQL User Community members (MyNA)
      • MySQL Server, MySQL Workbench and MySQL Shell by MySQL GBU 
    • Please watch organizers' website for more details.
  • PerconaLive, Amsterdam, Holland, September 30-October 2, 2019
    • MySQL team is going to become Silver partner of PerconaLive Amsterdam this year. Do not miss the chance to talk to our experts at MySQL booth in the expo area & come to multiple MySQL talks which were accepted, see below:
      • "MySQL 8.0: The New Replication Features" given by Luis Soares, the MySQL SW Development Director.
      • "MySQL 8.0 InnoDB Cluster - Easiest Tutorial!" given by Kenny Gryp, the MySQL Principal Product Manager & Frederick Descamps, the MySQL Community Manager.
      • "MySQL InnoDB Cluster - Advanced configuration & operation" given by Pedro Gomez, the Hardware Sales Representative & Frederick Descamps, the MySQL Community Manager.
      • "InnoDB management and scalability improvements in MySQL 8." given by Sunny Bains, the Senior Software Development Director.
      • "MySQL Shell : the best DBA tool ? - Extend the Shell with the new plugin infrastructure" given by Frederick Descamps, the MySQL Community Manager.
      • "MySQL 8.0 Performance: Scalability & Benchmarks" given by Dimitri Kravtchuk, the Performance Architect.
      • "Automatic Upgrade and New Error Logging in MySQL 8.0" given by Stale Deraas, the Software Development Director.
      • "JSON Array Indexes in MySQL" given by Norvald Ryeng, the Software Development Sr. Manager.
      • "How to Instrument Your Code in Performance Schema" given by Georgi Kodinov, the MySQL Software Development Director. 
    • We are looking forward to seeing and talking to you at PL 2019!
  • JCConf, Taipei, Taiwan, October 4, 2019
    • As tradition MySQL is a Silver sponsor of this Java conference. This year you can find our team at the MySQL booth in the expo area as well as find a MySQL talk as follows:
      • "How Java Leverage MySQL Cluster To Build Application with 99.9999% Availability" given by Ivan Tu, the MySQL Solution Engineering Manager. His talk is scheduled for 13:55-14:40. There is also a 3 minutes talk before sessions. We are looking forward to talking to you at JCConf this year!

MySQL Create User with Password

$
0
0

This tutorial explains how to create a user with password in MySQL. We’ll use the MySQL Create User command and describe it with the help of examples. By using this command, you can introduce a new user and grant him/her the required permissions or rights. Usually, you might be using the root user to access a database. The root user has complete control and can’t be restricted. Hence. It is mandatory to create users depending on the type of access s/he needs. And that’s where this command is going to help. MySQL Create User with Password The MySQL Create User

The post MySQL Create User with Password appeared first on Learn Programming and Software Testing.

Percona Live Europe Presents: Test Like a Boss

$
0
0

My first talk is a tutorial Testing like a boss: Deploy and Test Complex Topologies With a Single Command, scheduled at Percona Live Europe in Amsterdam on September 30th at 13:30.

My second talk is Amazing sandboxes with dbdeployer scheduled on October 1st at 11:00. It is the same topic as the tutorial, but covers a narrow set of features, all in the *amazing* category.

The tutorial introduces a challenging topic, because when people hear testing, they imagine a troop of monkeys fiddling with a keyboard and a mouse, endlessly repeating a boring task. What I want to show is that testing is a creative activity and, with the right tools and mindset, it could be exciting and rewarding. During my work as a quality assurance engineer, I have always seen a boring task as an opportunity to automate. dbdeployer, the tool at the heart of my talk, was born from one such challenge. While working as a MySQL consultant, I realized that every customer was using a different version of MySQL. When they had a problem, I couldn’t just use the latest and greatest version and recommend they upgrade: almost nobody wanted to even consider that, and I can see the point. Sometimes, upgrading is a huge task that should be planned appropriately, and not done as a troubleshooting measure. If I wanted to assist my customers, I had to install their version, reproduce the problem, and propose a solution. After installing and reinstalling several versions of MySQL manually, and juggling dozens of options to use the right version for the right task, I decided to make a tool for that purpose. That was in 2006, and since then the tool has evolved to handle the newest features of MySQL, was rewritten almost two years ago, and now is been adopted by several categories of database professionals: developers, DBAs, support engineers, and quality assurance engineers.

Looking at the user base of dbdeployer, it’s easy to reconsider the concept of testing: it could be exploring the latest MySQL or Percona Server release, or a building a sample Group Replication or Percona XtraDB Cluster, or comparing a given setup across different versions of MySQL. Still unconvinced? Read on!

What’s the catch? What do attendees get from attending?

In addition to opening their eyes to the beauty of testing, this tutorial will show several activities that a normal user would consider difficult to perform, time consuming, and error prone.

The key message of this presentation is that users should focus on what to do, and leave the details of how to perform the task to the tools at their disposal. The examples will show that you can deploy complicated scenarios with just a few commands, usually in less than one minute, sometimes in less than ten seconds, and then spend your time with the real task, which is exploring, trying a particular feature, proving a point, and not doing manually and with errors what the tool can do for you quickly and precisely.

Some examples to water your mouth: you can deploy group replication in less than 30 seconds. And what about deploying two groups and running asynchronous replication between them? Even if you have done this before, this is a task that takes you quite a while. dbdeployer can run the whole setup (two clusters in group replication + asynchronous replication on top of it) in less than one minute. How about testing the new clone plugin? You can do it in a snap using dbdeployer as demonstrated recently by Simon Mudd , which proves the point that having the right tools makes your experiments easier.

Another example? MySQL upgrade: dbdeployer can run a server upgrade for you faster than you can say “blueberry muffin” or maybe not that fast, but surely faster than reading the manual and following the instructions.

What else is in store at PerconaLive? What will I do apart from charming the attendees?

Percona Live Amsterdam is chock-full of good talks. I know because I was part of the review committee that has examined hundreds of proposals, and painfully approved only a portion of them. Things that I look forward to:

  • The InnoDB Cluster tutorial on Monday. Although I have seen this talk several times, the cluster has been improved continuously, and it is useful to see it in action. Besides, Lefred’s style of presentation is so engaging that I enjoy it every time.
  • Jeremy Cole’s take on Google Cloud, on Tuesday afternoon. Jeremy has been at the top of the database game for long time, and his views are always stimulating.
  • Backing up Wikipedia, with Jaime Crespo and Manuel Arostegui. Seeing how big deployments are dealt with is a sobering experience, which I highly recommend to newcomers and experts alike.
  • ClickHouse materialized views, with Robert Hodges of Altinity. You may not be thrilled about the topic, but the speaker is a guarantee. Robert has been working with databases for several decades, and he knows his way around big data and difficult problems to solve. Looking forward to learning something new here.

There are many more talks that I encourage you to peruse in the agenda.

As usual, the best part of the conference is networking in the intervals and around the venue before and after the event. This is where the best morsels of knowledge land with serendipity in my plate. See you soon!

If you haven’t yet registered, then you are invited to use the code CMESPEAK-GIUSEPPE for a 20% discount.

The content in this blog is provided in good faith by members of the open source community. Percona has not edited or tested the technical content. Views expressed are the authors’ own. When using the advice from this or any other online resource test ideas before applying them to your production systems, and always secure a working back up.

The post Percona Live Europe Presents: Test Like a Boss appeared first on Percona Community Blog.

Upgrading from MySQL 5.7 to MySQL 8.0 Part II

$
0
0

Reserved Words and UTF8MB4 Issues

The upgrade checker utility in the new MySQL Sell will warn you about potential problems.  The two most common problems I have seen are finding out one of your column names is a reserved word and character sets.

Reserved Words

You will spot reserved word issues on the second step of the upgrade check:
2) Usage of db objects with names conflicting with reserved keywords in 8.0
  Warning: The following objects have names that conflict with reserved
    keywords that are new to 8.0. Ensure queries sent by your applications use
    `quotes` when referring to them or they will result in errors.
  More information:
    https://dev.mysql.com/doc/refman/en/keywords.html

  davetest.reserved_word.over - Column name

In the above we are being told that in the schema 'davetest' in the table 'reserved_word' that there is a column named 'over' that conflicts with the newly added reserved word OVER.

There are two possible fixes.  One is to quote with back ticks (` not ') the column name for the rest of the lifetime of that table. You can use the back ticked item but have to remember to ALWAYS back tick the column name. Two is to rename 'over' to something else that is not a reserved word. 

UTF8 May Not Equal UTF8MB4

One of the big changes in MySQL 8.0 is the support for UTF8MB4 which includes support for version 9 of the Unicode character set. Before 8.0 UTF8 really meant UTF8MB3.  3 does not have full support for the forth plane which means no Chinese, Japanese, or Korean language support or support for emojis.

What We Used To Do


The past several years had most folks creating databases & schemas with UTF8 like the following:

CREATE DATABASE mydb  CHARACTER SET utf8  COLLATE utf8_general_ci;

This provides better support for CJK than say Latin1 but still falls short.  And if you run the util.checkForServerUpgrade(), the third step will tell you the following:

util.checkForServerUpgrade('root@localhost:3306') output for #3
And it tell you which schemas and tables should be updated to UTF8MB4.
The schema and table that need to be updated to UTF8MB4

The Fix

The good news is that is relatively easy, if not a little tedious, to convert.  First start with the database/schema.

ALTER SCHEMA davetest CHARACTER SET UTFMB4;

And for each table you will have to change the default and then change each column that uses a character set collation:

ALTER TABLE mytest DEFAULT CHARACTER SET UTF8MBF,
MODIFY COLUMN name CHARACTER SET utf8mb4 COLLATE utf8mb4_900_ai_ci;

Yes, this conversion is a little painful and tedious. But it does let you have access to all the Unicode characters.







Using Magento 2’s MySQL queue for order post-processing

$
0
0

I’ve been away from writing blog posts — the last one was more than two years ago. I decided to write one on this topic, however; I found out that implementing a queue was harder than it should be (in my opinion). Although Magento’s shenanigans don’t really surprise me anymore, the complexity of getting a simple queue up and running caught me (and my estimate) by surprise. There’s a few other blog posts on this topic already, but I found they don’t quite get into the nitty gritty that you potent...

SQL CHARINDEX Function Example

$
0
0
SQL CHARINDEX Function Example

SQL CHARINDEX Function Example is today’s topic. SQL CHARINDEX function is used for returning the location of a substring of a given string. SQL CHARINDEX function is not case-sensitive. SQL CHARINDEX function searches for a substring inside a string starting from a specified location.

It returns the position of the substring found in the searched string, or zero if the substring is not found. The starting position returned is 1-based, not 0-based.

SQL CHARINDEX Function

The CHARINDEX() function searches for a substring in a string and returns the position. If the substring is not found, this function returns 0. The function performs a case-insensitive search.

See the following syntax.

SELECT CHARINDEX (substring, input_string, [start_position] )

PARAMETERS

  1. Substring: The substring that you want to find within the input_string.
  2. Input_string: The String which is used for searching the substring.
  3. Start_position: The starting index from where searching will start. It is completely optional.

NOTE

  1. By default, the starting index will be 1.
  2. If the substring is not found within the string, then the function will return 0.

See the following examples.

SELECT CHARINDEX ('a', 'AppDividend.com');

See the output.

1

EXPLANATION

As a was present in the first index, so 1 was returned as the output. As the function is not case sensitive, so, there was no error.

SELECT CHARINDEX ('p', 'Appdividend.com', 2);

See the output.

3

EXPLANATION

As the starting index was from 2, so the function returned 3 as output. If starting index was not 2, then the output would have been 2.

SELECT CHARINDEX ('IS', 'HONESTY IS THE BEST POLICY');

See the output.

9

EXPLANATION

As IS was starting from the 9th index. Therefore, 9 was returned as output.

SELECT CHARINDEX ('J', 'AppDividend.com');

See the output.

0

EXPLANATION

As J was not present in the given string. So, 0 was returned as output.

Let’s apply the function in a Table.

Table: Employee

Emp_id Emp_name Email City State Salary
101 Rohit Raj Rohit111@gmail.com Patna Bihar 30000
102 Shiva Rana Shiv2345@gmail.com Jalandhar Punjab 20000
103 Karan Kumar Karan123@gmail.com Allahabad Uttar Pradesh 40000
104 Suraj Bhakat Suraj21254@gmail.com Kolkata West Bengal 60000
105 Akash Cherukuri Akash0001@gmail.com Vizag Andhra Pradesh 70000

 

Now, suppose we want to count the number of characters before the “@” symbol form email column.

Then the following query has to be written,

QUERY

Select Emp_id, Emp_name, CHARINDEX (‘@’, Email) AS Count 
from Employee;

Output:

Emp_id Emp_name Count
101 Rohit Raj 8
102 Shiva Rana 8
103 Karan Kumar 8
104 Suraj Bhakat 10
105 Akash Cherukuri 9

 

As you can see that the number of characters before “@” was displayed under the column named Count.

Using CHARINDEX() function to perform a case-insensitive search

This statement shows a case-insensitive search for the string ‘APPDIVIDEND‘ in ‘This is appdividend CHARINDEX’:

SELECT 
    CHARINDEX(
        'APPDIVIDEND', 
        'This is appdividend CHARINDEX'
    ) position;

Finally, SQL CHARINDEX Function Example is over.

Recommended Posts

Stuff Function In SQL Tutorial

Char Function In SQL Tutorial

ASCII Function In SQL

SQL TRIM Function Example

Substring In SQL

The post SQL CHARINDEX Function Example appeared first on AppDividend.

Make It Faster: Improving MySQL Write Performance for Tungsten Cluster Slaves

$
0
0

Overview

The Skinny

In this blog post we explore various options for performance tuning MySQL server for better slave replication performance.

A Tungsten Cluster relies upon the Tungsten Replicator to move events from the master node to the slaves. Once the event has been transferred to the slave as THL on disk, the slave applier will then attempt to write it to the database. The Replicator can only apply events as fast as MySQL allows. If the MySQL server is somehow slow or blocking, then the Replicator will be as well.

A properly-tuned database server in addition to infrastructure and SysAdmin best practices will go quite a long way towards high-performance slave apply.


The Question

Recently, a customer asked us:

During one of our load tests, we had a peak of 60k writes/min, averaging around 40k w/m. During this period, we saw an applied latency of 100-160 seconds. Is it possible to improve the replication latency on the slaves?


The Summary

Where To Look and What For?

When performance tuning, we normally examine the configuration and logs for the following layers:

  • Tungsten Replicator
  • MySQL server
  • Storage
  • Network/Firewall
  • Hardware & OS

The Rules

What are Performance Tuning Best Practices?

Before we dive into the various layers, let’s review the performance tuning basics that I have learned over the years:

  • Performance tuning is a slow, iterative process.
  • Change one thing at a time and test carefully.
  • Document your changes and test results.
  • Go for the low-hanging fruit early on. Sometimes the smallest changes may have the largest results, i.e. adding a proper index on a table.
  • As soon as you remove one bottleneck, the next one will appear. Iterate!
  • Divide and Conquer – pick a spot and ensure everything is working properly on both sides. this often helps in isolating issues.
  • Start at the top and work your way down the layers. Test, test, test!
  • Start at the bottom and work your way up the layers. Test, test, test!
  • When in doubt, ask, then document.
  • Read the documentation. Then read it again.
  • Ensure consistency amongst all nodes at every layer.
  • Most of all, do not assume.

Tungsten Replicator

The Short Version

We always start off by checking the replicator applier stages, of which there are three.

On a slave, if the appliedLatency of the remote-to-thl stage is low, but the appliedLatency of both the thl-to-q and q-to-dbms stages are high, then the issue is almost always with the MySQL server somehow.

For example, on a healthy cluster:

On a Master Node:
shell> trepctl status -name tasks | egrep 'applied|stage'

appliedLastEventId    : mysql-bin.000046:0000000065129638;-1
appliedLastSeqno      : 2656221
appliedLatency        : 0.279
stage                 : binlog-to-q

appliedLastEventId    : mysql-bin.000046:0000000065129638;-1
appliedLastSeqno      : 2656221
appliedLatency        : 0.279
stage                 : q-to-thl

On a Slave Node:
shell> trepctl status -name tasks | egrep 'applied|stage'

appliedLastEventId    : mysql-bin.000046:0000000065077978;-1
appliedLastSeqno      : 2656191
appliedLatency        : 0.345
stage                 : remote-to-thl

appliedLastEventId    : mysql-bin.000046:0000000065077978;-1
appliedLastSeqno      : 2656191
appliedLatency        : 0.371
stage                 : thl-to-q

appliedLastEventId    : mysql-bin.000046:0000000065077978;-1
appliedLastSeqno      : 2656191
appliedLatency        : 0.374
stage                 : q-to-dbms

For more information about stages, please visit the following blog post: Mastering Tungsten Replicator Series: Understanding Pipelines and Stages

Quick Tech “Tool Tip”
Here is a handy command to describe the summary progress of each stage on that node, refreshing every two seconds:

trepctl perf -r 2

MySQL Server

What a Lovely Tune
  • The first thing to do would be to enable the slow query logs just to validate that there is nothing blocking faster queries behind it. Since the applier is single-threaded, just one repeated slow query can create a huge bottleneck.
  • Next, SHOW FULL PROCESSLIST on the slaves during the latency would be helpful to identify what may be locking or blocking.
  • Use the MySQL EXPLAIN command to better understand why queries are slow.
  • Make sure there are no redundant indexes.
  • Does every table have a Primary Key?
  • What type of replication is enabled in MySQL – STATEMENT, MIXED or ROW? For active/passive clusters, we recommend MIXED, and for active/active clusters, use ROW to ensure data integrity across masters. ROW will increase latency due to the sheer volume of data transmitted as compared to STATEMENT or MIXED.
  • Are the tables InnoDB? If so, do you have lots of memory? can you load the tables into RAM and then sync to disk? This could help to avoid the physical SERIAL disk i/o that can create bottlenecks, even if the i/o channel itself is not full
  • Check for the use of Unique indexes, which disable the InnoDB change buffering performance boost. InnoDB has change buffering (previously called the insert buffer), which is a feature to delay building secondary indexes that are not unique, and merge writes. It can boost insert performance by quite a lot, and it’s enabled by default.
  • Finally, how large are the affected tables and schemas in terms of row size and byte size? Can the tables be split? Can the databases be split?

Key MySQL my.cnf Configuration Parameters to Check:

For this specific customer, we identified four (4) “hot” tables in the slow query logs, which turned out to have 2 million or more rows each. This asks the database to perform some i/o intensive operations.
Once the issue was clearly localized to the four tables, the scope narrowed somewhat, implying an indexing, query or disk i/o-based bottleneck.


Storage

Disk Inside and Out
  • Disk I/O is normally the slowest part of any compute workflow because disk is often much slower than physical memory. No matter how fast the underlying SSD is, there are physical limitations to overcome, especially with SAN and Cloud-based storage.
  • For example, when using AWS EC2, consider using enhanced EBS I/O with provisioned IOPS if you are not already doing so, which would provide faster performance at an increased cost.
  • Not having separated volumes for different purposes will always degrade performance because of disk contention. For example, ensure separate volumes for (at least) root, mysql data, mysql binlogs and THL files.
  • Then stripe each filesystems for MySQL over multiple volumes using RAID of some sort (i.e. RAID-0), so that there are multiple I/O channels in use at the same time for the same filesystem.
  • This layered disk architecture provides for a large number of parallel disk I/O channels, giving a much higher throughput at a much lower latency.
  • What is the filesystem type? (i.e. xfs, ext4, etc…) because journaling filesystems are very slow. Consider using a non-journaling file system, or disabling journaling. We suggest using xfs.
  • Mount the filesystem using the -noatime option

Network/Router/Firewall

The Network Really IS the Computer
  • Ensure sufficient bandwidth, and a very low error rate.
  • Confirm the various hops have sufficient cpu, ram and bandwidth
  • Is the firewall able to keep up?

Operating System

SysAdmins to the Rescue, As Usual
  • Is there enough CPU?
  • Is there enough RAM?
  • Check nproc and ofiles limits

Advanced Tungsten Replicator

The Parallel (Apply) Universe

After making sure that all reasonable efforts have been made to properly evaluate the above solutions, there is an advanced feature available to try: Parallel Apply.

Tungsten Replicator by default uses a single-threaded applier, so it can get about 10,000 updates per second maximum, depending on the round trip time, and so on. Since MySQL server is multi-threaded, the master is able to write faster than the slaves.

To increase that limit, Tungsten Replicator offers Parallel Apply, which employs multiple replication apply threads, one per shard.

https://docs.continuent.com/tungsten-clustering-6.0/deployment-parallel.html

By default, we shard by database, with one shard created per database schema. If there is a cross-database query, all other threads block until that one completes, slowing performance down dramatically.

This means Parallel apply is best suited for environments that equally busy writes for every database. Having many databases, but only one or two as hot defeats the design and purpose of Parallel Apply.

Again, any cross-shard query will force the Replicator back into single-threaded mode to ensure data integrity, with the result of having no performance gain, or even degradation as now the Replicator has to keep switching modes.

Tungsten Replicator can also shard by table, with the same caveats, but this time cross-TABLE queries will block other threads, making this somewhat less useful than desired based on most query designs.

http://docs.continuent.com/tungsten-replicator-6.1/filters-reference-shardbytable.html

Important questions before implementing Parallel Apply:

  • Do you have just one database schema or multiple?
  • If single, do the bulk of your queries cross tables or use single tables?
  • If multiple databases, are they de-coupled or do you do a bunch of cross-database queries?

The Answer

What WAS the Solution After All?

For this customer, the following changes improved performance to acceptable levels:

  • The THL was being written to the same location as the MySQL binary logs, creating contention. Moving the THL directory to a different location (/logs) improved performance.
  • Because the nodes are AWS EC2 instances, converting volumes from GP2 to Provisioned IOPS allowed the slave to keep up with replication much better.
  • Several MySQL configuration values were modified, which also decreased the applied latency on the slaves:
    innodb_io_capacity=1000 (Interestingly, lowering this from 10k to 1k led to a significant improvement in latency, despite the EBS volume being provisioned for 10k iops)
    innodb_io_capacity_max=2000
    innodb_adaptive_hash_index=0
    innodb_lru_scan_depth=2048
    performance_schema=0

The Library

Please read the docs!

For more information about how to use the Tungsten Replicator, please see Mastering Tungsten Replicator Series: Command Line Superpowers

For more in-depth discussion about MySQL database tuning, here are some excellent blog posts by Morgan Tocker:
http://www.tocker.ca/2013/09/17/what-to-tune-in-mysql-56-after-installation.html
http://www.tocker.ca/2013/05/06/when-does-mysql-perform-io.html

For more technical information about Tungsten clusters, please visit https://docs.continuent.com


Summary

The Wrap-Up

Clearly, there are many, many things to think about when it comes to MySQL performance tuning – this blog post barely scratches the surface of the subject. Remember, performance tuning is all about iterative effort over time!

Tungsten Clustering is the most flexible, performant global database layer available today – use it underlying your SaaS offering as a strong base upon which to grow your worldwide business!

For more information, please visit https://www.continuent.com/solutions

Want to learn more or run a POC? Contact us.

Running Percona XtraDB Cluster on Raspberry PI 3

$
0
0
Percona XtraDB Cluster on Raspberry PI 3

Percona XtraDB Cluster on Raspberry PI 3In a previous post, I showed you how to compile Percona Mysql 5.7 on Raspberry PI 3. Now, I’ll show you how to compile and run the latest version of Percona XtraDB Cluster 5.7.26.

We will need at least 3 RaspberryPi 3 boards, and I recommend you use an external SSD drive to compile and use as MySQL’s “datadir” to avoid the stalls associated with the microSD card, which will cause PXC to run slow.

In this post, we are going to run many OS commands and configure PXC. I recommend having minimal knowledge about PXC and Linux commands.

How to install CentOS

Download the centos image from this link http://mirror.ufro.cl/centos-altarch/7.6.1810/isos/armhfp/CentOS-Userland-7-armv7hl-RaspberryPI-Minimal-1810-sda.raw.xz

I’m using this open source software https://www.balena.io/etcher/ to flash/burn the microSD card because it is very simple and works fine. I recommend using a 16GB card or larger.

If the previous process finished ok, take out the microSD card and put it into the raspberry and boot it. Wait until the boot process finishes and log in with this user and password

user: root
password: centos

By default, the root partition is very small and you need to expand it. Run the next command, this process is fast.

/usr/bin/rootfs-expand

Finally, to finish the installation process it is necessary to install many packages to compile PXC and percona-xtrabackup,

yum install -y cmake wget automake bzr gcc make telnet gcc-c++ vim libcurl-devel readline-devel ncurses-devel screen zlib-devel bison locate libaio libaio-devel autoconf socat libtool  libgcrypt-devel libev-devel vim-common check-devel openssl-devel boost-devel glib2-devel

Repeat all the previous steps over all those 3 dbnodes because some libs are needed to start mysql and to work with percona-xtrabackup.

How to compile PXC + Galera + Xtrabackup

I am using an external SSD disk because it’s faster than the microSD which I mounted on /mnt directory, so we will use this partition to download, compile, and create the datadir.

For the latest PXC version, download and decompress it using the following commands:

cd /mnt
wget https://www.percona.com/downloads/Percona-XtraDB-Cluster-57/Percona-XtraDB-Cluster-5.7.26-31.37/source/tarball/Percona-XtraDB-Cluster-5.7.26-31.37.tar.gz
tar zxf Percona-XtraDB-Cluster-5.7.26-31.37.tar.gz
cd Percona-XtraDB-Cluster-5.7.26-31.37

RaspberryPi3’s are not x86_64 architecture; it uses an ARMv7 which forces us to compile PXC from scratch. For me, this process took 6-ish hours. I recommend running the next commands in a screen session.

screen -SDRL compile_pxc
cmake -DINSTALL_LAYOUT=STANDALONE -DCMAKE_INSTALL_PREFIX=/mnt/pxc5726 -DDOWNLOAD_BOOST=ON -DWITH_BOOST=/mnt/sda1/my_boost -DWITH_WSREP=1 .
make
make install

Create a new OS user to be used by the mysql process.

useradd --no-create-home mysql

Now to continue it is necessary to create the datadir directory. I recommend to use the SSD disk attached and set the mysql permissions to the directory:

mkdir /mnt/pxc5726/data/
chown mysql.mysql /mnt/pxc5726/data/

Configure my.cnf with the minimal params to start mysql.

vim /etc/my.cnf

[client]
socket=/mnt/pxc5726/data/mysql.sock

[mysqld]
datadir = /mnt/pxc5726/data
binlog-format = row
log_bin = /mnt/pxc5726/data/binlog
innodb_buffer_pool_size = 128M
socket=/mnt/pxc5726/data/mysql.sock
symbolic-links=0

wsrep_provider=/mnt/pxc5726/libgalera_smm.so

wsrep_on=ON
wsrep_cluster_name="pxc-cluster"
wsrep_cluster_address="gcomm://192.168.88.134"

wsrep_node_name="pxc1"
wsrep_node_address=192.168.88.134

wsrep_debug=1

wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=sstuser:passw0rd

pxc_strict_mode=ENFORCING

[mysqld_safe]
log-error=/mnt/pxc5726/data/mysqld.log
pid-file=/mnt/pxc5726/data/mysqld.pid

So far we’ve only compiled PXC. Before we can start the mysql process, we also need to compile the Galera library, as, without this library, mysql will start as a standalone db-node and will not have any “cluster” capabilities.

To build libgalera_smm.so you need to install scons.

Download using the next command:

cd /mnt
wget http://prdownloads.sourceforge.net/scons/scons-3.1.0.tar.gz
tar zxf scons-3.1.0.tar.gz
cd scons-3.1.0
python setup.py install

Now we will proceed to compile libgalera. The source code for this library exists in the Percona-XtraDB-Cluster-57 directory download:

cd /mnt/Percona-XtraDB-Cluster-5.7.26-31.37/percona-xtradb-cluster-galera
scons -j4 libgalera_smm.so debug=3 psi=1 BOOSTINCLUDE=/mnt/my_boost/boost_1_59_0/boost BOOST_LIBS=/mnt/my_boost/boost_1_59_0/libs

If the compile process finishes ok, it will create a new file like this:

/mnt/Percona-XtraDB-Cluster-5.7.26-31.37/percona-xtradb-cluster-galera/libgalera_smm.so

I recommend copying libgalera_smm.so to the installed PXC directory to avoid deleting, in that case, remove the source directory.

cp /mnt/Percona-XtraDB-Cluster-5.7.26-31.37/percona-xtradb-cluster-galera/libgalera_smm.so /mnt/pxc5726

Also, this is useful because after installing and compiling all the packages we can create a compressed file and copy to the rest of the db-nodes to avoid having to compile these packages again.

The last step is to download and compile percona-xtrabackup. I used the latest version:

screen -SDRL compile_xtrabackup

cd /mnt
wget https://www.percona.com/downloads/Percona-XtraBackup-2.4/Percona-XtraBackup-2.4.15/source/tarball/percona-xtrabackup-2.4.15.tar.gz
tar zxf percona-xtrabackup-2.4.15.tar.gz
cd percona-xtrabackup-2.4.15
cmake -DBUILD_CONFIG=xtrabackup_release -DWITH_MAN_PAGES=OFF -DCMAKE_INSTALL_PREFIX=/mnt/xtrabackup .
make
make install

If all the previous steps were successful, we will add those binary directories in the PATH variable:

vim /etc/profile.d/percona.sh

export PATH=$PATH:/mnt/xtrabackup/bin:/mnt/pxc5726/bin

Save and exit and run the “export” command manually to set it in the active session:

export PATH=$PATH:/mnt/xtrabackup/bin:/mnt/pxc5726/bin

Well, so far we have PXC, Galera-lib, and percona-xtrabackup compiled for the ARMv7 architecture, which is all that is needed to work with PXC, so now we can start playing.

We will call the first host where we compiled “pxc1”. We will proceed to set the hostname:

$ vim /etc/hostname
pxc1

$ hostname pxc1
$ exit

It is necessary to connect again to ssh to refresh the hostname and you will see something like this:

$ ssh ip
[root@pxc1 ~]#

Now we are ready to open the ports needed by PXC;  xtrabackup, galera, and mysql.

$ firewall-cmd --permanent --add-port=3306/tcp
$ firewall-cmd --permanent --add-port=4567/tcp
$ firewall-cmd --permanent --add-port=4444/tcp

$ firewall-cmd --reload

$ firewall-cmd --list-ports
22/tcp 3306/tcp 4567/tcp 4444/tcp

Repeat the above procedures to set the hostname and open ports in the other db nodes.

Finally, to start the first node you’ll need to initialize the system databases and then launch the mysql process with the –wsrep-new-cluster option. This will bootstrap the cluster so that it starts with 1 node. Run the following from the command-line:

$ mysqld --initialize-insecure --user=mysql --basedir=/mnt/pxc5726 --datadir=/mnt/pxc5726/data
$ mysqld_safe --defaults-file=/etc/my.cnf --user=mysql --wsrep-new-cluster &

Check the mysql error log to see any errors:

$ tailf /mnt/pxc5726/data/mysqld.log

...
2019-09-08T23:23:17.415991Z 0 [Note] /mnt/pxc5726/bin/mysqld: ready for connections.
...

Create the new mysql user, and this will be used for xtrabackup to sync another db node on IST or SST process.

$ mysql

CREATE USER 'sstuser'@'localhost' IDENTIFIED BY 'passw0rd';
GRANT PROCESS, RELOAD, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'sstuser'@'localhost';
FLUSH PRIVILEGES;

Lastly, I recommend checking if the galera library was loaded successfully:

$ mysql

show global status where Variable_name='wsrep_provider_name' 
or Variable_name='wsrep_provider_name' 
or Variable_name='wsrep_provider_vendor' 
or Variable_name='wsrep_local_state' 
or Variable_name='wsrep_local_state_comment' 
or Variable_name='wsrep_cluster_size' 
or Variable_name='wsrep_cluster_status' 
or Variable_name='wsrep_connected' 
or Variable_name='wsrep_ready' 
or Variable_name='wsrep_evs_state' 
or Variable_name like 'wsrep_flow_control%';

You will see something like this:

+----------------------------------+-----------------------------------+
| Variable_name                    | Value                             |
+----------------------------------+-----------------------------------+
| wsrep_flow_control_paused_ns     | 0                                 |
| wsrep_flow_control_paused        | 0.000000                          |
| wsrep_flow_control_sent          | 0                                 |
| wsrep_flow_control_recv          | 0                                 |
| wsrep_flow_control_interval      | [ 100, 100 ]                      |
| wsrep_flow_control_interval_low  | 100                               |
| wsrep_flow_control_interval_high | 100                               |
| wsrep_flow_control_status        | OFF                               |
| wsrep_local_state                | 4                                 |
| wsrep_local_state_comment        | Synced                            |
| wsrep_evs_state                  | OPERATIONAL                       |
| wsrep_cluster_size               | 1                                 | <----
| wsrep_cluster_status             | Primary                           |
| wsrep_connected                  | ON                                |
| wsrep_provider_name              | Galera                            |
| wsrep_provider_vendor            | Codership Oy <info@codership.com> |
| wsrep_ready                      | ON                                |
+----------------------------------+-----------------------------------+

As you can see this is the first node and the cluster size is 1.

How to copy the previous compiled source code to the rest of the db nodes

You don’t need to compile again over all the rest of the db nodes, just compress PXC and Xtrabackup directories and copy to the rest of the db nodes, nothing else.

In the first step, we compiled and installed on the next directories:

/mnt/pxc5726
/mnt/xtrabackup

We’re going to proceed to compress both directories and copy to the other servers (pxc2 and pxc3)

$ cd /mnt
$ tar czf pxc5726.tgz pxc5726
$ tar czf xtrabackup.tgz xtrabackup

Let’s copy to each db node:

$ cd /mnt
$ scp pxc5726.tgz xtrabackup.tgz IP_PXC2:/mnt

Now connect to each db node and start decompressing, configure my.cnf, other stuff, and start mysql.

$ ssh IP_PXC2
$ cd /mnt
$ tar zxf pxc5726.tgz
$ tar zxf xtrabackup.tgz

From here we are going to repeat several steps that we did previously.

Connect to IP_PXC2.

$ ssh IP_PXC2

Add the next directories in the PATH variable:

vim /etc/profile.d/percona.sh

export PATH=$PATH:/mnt/xtrabackup/bin:/mnt/pxc5726/bin

Save and exit and run the “export” command manually to set it in the active session:

export PATH=$PATH:/mnt/xtrabackup/bin:/mnt/pxc5726/bin

Create a new OS user to be used by mysql process:

useradd --no-create-home mysql

Now to continue it’s necessary to create the datadir directory. I recommend using the SSD disk attached and set the mysql permissions to the directory.

mkdir /mnt/pxc5726/data/
chown mysql.mysql /mnt/pxc5726/data/

Configure my.cnf with the minimal params to start mysql.

vim /etc/my.cnf

[client]
socket=/mnt/pxc5726/data/mysql.sock

[mysqld]
datadir = /mnt/pxc5726/data
binlog-format = row
log_bin = /mnt/pxc5726/data/binlog
innodb_buffer_pool_size = 128M
socket=/mnt/pxc5726/data/mysql.sock
symbolic-links=0

wsrep_provider=/mnt/pxc5726/libgalera_smm.so

wsrep_on=ON
wsrep_cluster_name="pxc-cluster"
wsrep_cluster_address="gcomm://IP_PXC1,IP_PXC2"

wsrep_node_name="pxc2"
wsrep_node_address=IP_PXC2

wsrep_debug=1

wsrep_sst_method=xtrabackup-v2
wsrep_sst_auth=sstuser:passw0rd

pxc_strict_mode=ENFORCING

[mysqld_safe]
log-error=/mnt/pxc5726/data/mysqld.log
pid-file=/mnt/pxc5726/data/mysqld.pid

Now we need to start the second db node. This time you don’t need to add “–wsrep-new-cluster” param (from the second and next nodes it’s not needed), just start mysql and run the next command:

$ mysqld_safe --defaults-file=/etc/my.cnf --user=mysql &

Check the mysql error log to see any error:

$ tailf /mnt/pxc5726/data/mysqld.log

...
2019-09-08T23:53:17.415991Z 0 [Note] /mnt/pxc5726/bin/mysqld: ready for connections.
...

Check if the galera library was loaded successfully:

$ mysql

show global status where Variable_name='wsrep_provider_name' 
or Variable_name='wsrep_provider_name' 
or Variable_name='wsrep_provider_vendor' 
or Variable_name='wsrep_local_state' 
or Variable_name='wsrep_local_state_comment' 
or Variable_name='wsrep_cluster_size' 
or Variable_name='wsrep_cluster_status' 
or Variable_name='wsrep_connected' 
or Variable_name='wsrep_ready' 
or Variable_name='wsrep_evs_state' 
or Variable_name like 'wsrep_flow_control%';

You will see something like this:

+----------------------------------+-----------------------------------+
| Variable_name                    | Value                             |
+----------------------------------+-----------------------------------+
| wsrep_flow_control_paused_ns     | 0                                 |
| wsrep_flow_control_paused        | 0.000000                          |
| wsrep_flow_control_sent          | 0                                 |
| wsrep_flow_control_recv          | 0                                 |
| wsrep_flow_control_interval      | [ 100, 100 ]                      |
| wsrep_flow_control_interval_low  | 100                               |
| wsrep_flow_control_interval_high | 100                               |
| wsrep_flow_control_status        | OFF                               |
| wsrep_local_state                | 4                                 |
| wsrep_local_state_comment        | Synced                            |
| wsrep_evs_state                  | OPERATIONAL                       |
| wsrep_cluster_size               | 2                                 | <---
| wsrep_cluster_status             | Primary                           |
| wsrep_connected                  | ON                                |
| wsrep_provider_name              | Galera                            |
| wsrep_provider_vendor            | Codership Oy <info@codership.com> |
| wsrep_ready                      | ON                                |
+----------------------------------+-----------------------------------+

Excellent, we have the second node up, now is it’s part of the cluster and the cluster size is 2.

Repeat the previous steps to configure IP_PXC3 and nexts.

Summary

We are ready to start playing and doing a lot of tests. I recommend running sysbench to test how many transactions this environment supports, kill some nodes to test SST and IST, and I recommend using pt-online-schema-change and check this blog “How to Perform Compatible Schema Changes in Percona XtraDB Cluster” to learn how this tool works in PXC.

I hope you enjoyed this guide, and if you want to compile other PXC 5.7.X versions, please go ahead, the steps will be very similar.

Comparing DBaaS Failover Solutions to Manual Recovery Setups

$
0
0

We have recently written several blogs covering how different cloud providers handle database failover. We compared failover performance in Amazon Aurora, Amazon RDS and ClusterControl, tested the failover behavior in Amazon RDS, and also on Google Cloud Platform. While those services provide great options when it comes to failover, they may not be right for every application.

In this blog post we will spend a bit of time analysing the pros and cons of using the DBaaS solutions compared with designing an environment manually or by using a database management platform, like ClusterControl.

Implementing High Availability Databases with Managed Solutions

The primary reason to use existing solutions is ease of use. You can deploy a highly available solution with automated failover in just a couple of clicks. There’s no need for combining different tools together, managing the databases by hand, deploying tools, writing scripts, designing the monitoring, or any other database management operations. Everything is already in place. This can seriously reduce the learning curve and requires less experience to set up a highly-available environment for the databases; allowing basically everyone to deploy such setups.

In most of the cases with these solutions, the failover process is executed within a reasonable time. It may be blazing fast as with Amazon Aurora or somewhat slower as with Google Cloud Platform SQL nodes. For the majority of the cases, these types of results are acceptable. 

The bottom line. If you can accept 30 - 60 seconds of downtime, you should be ok using any of the DBaaS platforms.

The Downside of Using a Managed Solution for HA

While DBaaS solutions are simple to use, they also come with some serious drawbacks. For starters, there is always a vendor lock-in component to consider. Once you deploy a cluster in Amazon Web Services it is quite tricky to migrate out of that provider. There are no easy methods to download the full dataset through a physical backup. With most providers, only manually executed logical backups are available. Sure, there are always options to achieve this, but it is typically a complex, time-consuming process, which still may require some downtime after all.

Using a provider like Amazon RDS also comes with limitations. Some actions cannot be easily performed which would be very simple to accomplish on environments deployed in a fully user-controlled manner (e.g. AWS EC2). Some of these limitations have already been covered in other blogs, but to summarize is that no DBaaS service gives you the same level of flexibility as regular MySQL GTID-based replication. You can promote any slave, you can re-slave every node off any other...virtually every action is possible. With tools like RDS you face design-induced limitations you cannot bypass.

The problem is also with an ability to understand performance details. When you design your own highly available setup, you become knowledgeable about potential performance issues that may show up. On the other hand, RDS and similar environments are pretty much “black boxes.” Yes, we have learned that Amazon RDS uses DRBD to create a shadow copy of the master, we know that Aurora uses shared, replicated storage to implement very fast failovers. That’s just a general knowledge. We cannot tell what are the performance implications of those solutions other than what we might casually notice. What are common issues associated with them? How stable are those solutions? Only the developers behind the solution know for sure.

What is the Alternative to DBaaS Solutions?

You may wonder, is there an alternative to DBaaS? After all, it is so convenient to run the managed service where you can access most of the typical actions via UI. You can create and restore backups, failover is handled automatically for you. The environment is easy-to-use which can be compelling for companies who do not have dedicated and experienced staff for dealing with databases.

ClusterControl provides a great alternative to cloud-based DBaaS services. It provides you with a graphical user interface, which can be used to deploy, manage, and monitor open source databases. 

In couple of clicks you can easily deploy a highly-available database cluster, with automated failover (faster than most of the DBaaS offerings), backup management, advanced monitoring, and other features like integration with external tools (e.g. Slack or PagerDuty) or upgrade management. All this while completely avoiding vendor lock-in. 

ClusterControl doesn’t care where your databases are located as long as it can connect to them using SSH. You can have setups in cloud, on-prem, or in a mixed environment of multiple cloud providers. As long as connectivity is there, ClusterControl will be able to manage the environment. Utilizing the solutions you want (and not the ones that you are not familiar nor aware of) allows you to take full control over the environment at any point in time. 

Whatever setup you deployed with ClusterControl, you can easily manage it in a more traditional, manual or scripted way. ClusterControl even provides you with command line interface, which will let you incorporate tasks executed by ClusterControl into your shell scripts. You have all the control you want - nothing is a black box, every piece of the environment would be built using open source solutions combined together and deployed by ClusterControl.

Let’s take a look at how easily you can deploy a MySQL Replication cluster using ClusterControl. Let’s assume you have the environment prepared with ClusterControl installed on one instance and all other nodes accessible via SSH from ClusterControl host.

ClusterControl Deployment Wizard

We will start with picking the “Deploy” wizard.

ClusterControl Deployment Wizard

At the first step we have to define how ClusterControl should connect to the nodes on which databases are to be deployed. Both root access or sudo (with or without the password) are supported.

ClusterControl Deployment Wizard

Then, we want to pick a vendor, version and pass the password for the administrative user in our MySQL database.

ClusterControl Deployment Wizard

Finally, we want to define the topology for our new cluster. As you can see, this is already quite complex setup, unlike something you can deploy using AWS RDS or GCP SQL node.

ClusterControl Jobs

All we have to do now is to wait for the process to complete. ClusterControl will do its best to understand the environment it is deploying to and install required set of packages, including the database itself.

ClusterControl Cluster List

Once the cluster is up-and-running, you can proceed with deploying the proxy layer (which will provide your application with a single point of entry into the database layer). This is more or less what happens behind the scenes with DBaaS, where you also have endpoints to connect to the database cluster. It is quite common to use a single endpoint for writes and multiple endpoints for reaching particular replicas.

Database Cluster Topology

Here we will use ProxySQL, which will do the dirty work for us - it will understand the topology, sends writes only to the master and load balance read-only queries across all replicas that we have.

To deploy ProxySQL we will go to Manage -> Load Balancers.

Add Database Load Balancer ClusterControl

We have to fill all required fields: hosts to deploy on, credentials for the administrative and monitoring user, we may import existing user from MySQL into ProxySQL or create a new one. All the details about ProxySQL can be easily found in multiple blogs in our blog section.

We want at least two ProxySQL nodes to be deployed to ensure high-availability. Then, once they are deployed, we will deploy Keepalived on top of ProxySQL. This will ensure that Virtual IP will be configured and pointing to one of the ProxySQL instances, as long as there will be at least one healthy node.

Add ProxySQL ClusterControl

Here is the only potential problem if you go with cloud environments where routing works in a way that you cannot easily bring up a network interface. In such case you will have to modify the configuration of Keepalived, introduce ‘notify_master’ script and use a script, which will make the necessary IP changes - in case of EC2 it would have to detach Elastic IP from one host and attach it to the other host. 

There are plenty of instructions on how to do that using widely-tested open source software in setups deployed by ClusterControl. You can easily find additional information, tips, and how-to’s which are relevant to your particular environment.

Database Cluster Topology with Load Balancer

Conclusion

We hope you found this blog post insightful. If you would like to test ClusterControl, it comes with a 30 day enterprise trial where you have available all the features. You can download it for free and test if it fits in your environment.

OOW 2019 – MySQL Highlights

$
0
0

We just wrapped up what was a very exciting OOW 2019 - San Francisco for MySQL.  Our MySQL track included 29 sessions, a keynote with 2 customer testimonials (Mercari and WePay), 1 tutorial, 1 Hands-on lab, 1 Birds of a Feather, and our always fun and enjoyable MySQL Community Reception.  

A BIG Thank You to the companies who came to share their experience and testimonial about how MySQL helps scale their company such as Facebook, JP Morgan Chase WePay, Credorax, Mercari, Zuora, and more.

Highlights for MySQL:

  • MySQL 8.0,  fastest adoption of any version with over 26% in a year
  • New MySQL Analytics Service, faster than Google BigQuery says Mercari
  • HA with MySQL InnoDB Cluster
  • Microservices with MySQL and Vitesse on Kubernetes
  • NoSQL with NodeJS and MySQL Document Store

Many of the sessions are now available online:

Keynote: State of the Dolphin with:

  • Rich Mason,, MySQL General Manager
  • Tomas Ulin, MySQL VP of Engineering
  • Nipun Agarwal, Oracle Labs, VP of R&D
  • Kenichi Sasaki, Mercari
  • Rich Steenburg, WePay

Recorded sessions:

MySQL 8.0 at Facebook

Managing MySQL at Scale in Facebook

Python and MySQL 8.0 Document Store

Running MySQL on Kubernetes the Easy Way

MySQL with ProxySQL at Zuora

What’s New in MySQL Optimizer and Executor?

Using MySQL as a Document Store with Native APIs

Building Carefree Data-Driven Applications with the MySQL X DevAPI

Foreign Key Support in MySQL 8.0: Change, Opportunities, and More...

 

If you’d like to participate at one of our Oracle Open World events, or at a MySQL event, to share your experience and knowledge of MySQL and how MySQL helps scale your company, contact us through Chat or through your Sales representative. 

SQL DIFFERENCE Function Example | Understanding Difference Method

$
0
0
SQL DIFFERENCE Function Example | Understanding Difference Method

SQL DIFFERENCE Function Example | Understanding Difference Method is today’s topic. SQL DIFFERENCE function is used for returning the difference between the Soundex values. A Soundex value is four characters long. If two strings sound the same, then their Soundex values will be the same. If two strings sound entirely different, then none of the characters Soundex values will be the same.

SQL DIFFERENCE Function

The SQL DIFFERENCE, one of the String Function, compares two SOUNDEX values, and returns the integer.

An integer value indicates the match for the two SOUNDEX values, from 0 to 4. The 0 indicates weak or no similarity between the SOUNDEX values. 4 indicates strong similarity or identically SOUNDEX values.

For example, peace and piece sound the same so that they will have the same Soundex values.

SELECT SOUNDEX ('piece') AS Piece, SOUNDEX ('Peace') AS Peace;

See the output.

Piece Peace
P200 P200

 

See the following syntax.

SELECT DIFFERENCE (input_string1, input_string2);

Parameters

  1. DIFFERENCE: Used for comparing two Soundex values.
  2. Input_string1, input_string_2: Strings whose Soundex values is to be considered.

Examples

  1. STRONG SIMILARITY

Query

SELECT SOUNDEX('PIECE') AS PIECE, SOUNDEX('PEACE') AS PEACE, DIFFERENCE ('PIECE', 'PEACE') 
AS SIMILARITY;

Output

As the Soundex values of both the strings are the same and as there is a strong similarity between them, so 4 is returned.

Query

SELECT SOUNDEX (‘TWO’) AS TWO, SOUNDEX(‘TOO’) AS TOO, DIFFERENCE (‘TWO’, ‘TOO’) AS SIMILARITY;

Output

TWO TOO SIMILARITY
T000 T000 4

 

Less Similarity

See the following query.

SELECT SOUNDEX (‘COFFEE’) AS COFEE, SOUNDEX(‘LAPTOP’) AS LAPTOP, DIFFERENCE (‘COFFEE’, ‘LAPTOP’) 
AS SIMILARITY;

Output

COFFEE LAPTOP SIMILARITY
C100 L131 1

 

In the above query, both the strings, sounds were different, so there was a minimal similarity between two strings. 1 was returned as output because 1 character of Soundex values had a match.

No Similarity

Query

SELECT SOUNDEX('Tree') AS Tree, SOUNDEX('Captivated') AS Captivated, DIFFERENCE ('Tree', 'Captivated') 
AS SIMILARITY;

Output

Tree Captivated SIMILARITY
T600 C131 0

 

In the above output, there is no match between any characters. So, the value returned was 0.

Finally, SQL DIFFERENCE Function Example | Understanding Difference Method is over.

Recommended Posts

SQL CHARINDEX Function Example

Subqueries In SQL Tutorial

Alias In SQL Tutorial

SQL TOP, LIMIT Or ROWNUM Clause Example Tutorial

What Is SQL Injection

The post SQL DIFFERENCE Function Example | Understanding Difference Method appeared first on AppDividend.


SQL CONCAT_WS Function Example | CONCAT_WS Method In SQL

$
0
0
SQL CONCAT_WS Function Example | CONCAT_WS Method In SQL

SQL CONCAT_WS Function Example | CONCAT_WS Method In SQL is today’s topic. The SQL CONCAT_WS function is used to join two or more expressions separated by a separator. It takes up to 255 input strings which are further joined by a function. If we want to perform the join operation, CONCAT requires at least 2 strings. If it is provided with only 1 string, it will raise the error.

SQL CONCAT_WS Function

If any non-character string values are passed into the function, it will be implicitly converted to the strings before concatenating.

If NULL is added to the function, it converts it into the empty string with VARCHAR (1).

See the following syntax.

SELECT CONCAT_WS (separator, expression1, expression2, expression3…)

Parameters

Separator

This is the separator that is added between more than one expression. If the separator is NULL, then the function will return NULL.

expression1, expression2, expression3…:

These are the expressions that will be concatenated.

See the following example. We are using SQL SELECT Statement.

SELECT CONCAT_WS ('.', 'AppDividend', 'com');

Output

AppDividend.com

Explanation

Here “.” acts as a separator and is added between AppDividend and com.

See the following code.

SELECT CONCAT_WS (',', 1, 2, NULL, NULL, 3);

Output

1, 2, 3

Explanation

The above example demonstrated how concat_ws() function deals with NULL values. Here, the NULL values were ignored, and no separator was added between them.

Above were all the common examples to make clear how the Concat function works.

Let’s see the example with proper tables.

Consider table Employee.

Emp_id First_name Last_name City State Salary
101 Rohit Raj Patna Bihar 30000
201 Shivam Rana Jalandhar Punjab 20000
301 Karan Kumar Allahabad Uttar Pradesh 40000
401 Suraj Bhakat Kolkata West Bengal 60000
501 Akash Cherukuri Vizag Andhra Pradesh 70000

 

Now, suppose we want the full name of an employee from this table. Then, the following query has to be executed.

Query

Select First_name, Last_name, concat_ws(‘ ’, First_name, Last_Name) 
AS Full_name from Employee;

Output

First_name Last_name Full_name
Rohit Raj Rohit Raj
Shivam Rana Shivam Rana
Karan Kumar Karan Kumar
Suraj Bhakat Suraj Bhakat
Akash Cherukuri Akash Cherukuri

 

Here you can see that the full name of the employee is displayed separated by a separator which was space.

The CONCAT_WS() function joins the input strings into the single string.

It separates those concatenated strings with a separator particular in the first argument.

One thing to note that the CONCAT_WS() requires at least two input strings.

It means that if we pass zero or one input string argument, the function will raise the error.

The CONCAT_WS() function treats NULL as the empty string of type VARCHAR().

It also does not add a separator between NULLs.

Therefore, a CONCAT_WS() function can cleanly join the strings that may have blank values.

Use CONCAT_WS() function with table columns

The following statement uses the CONCAT_WS() function to join the values in the last_name and first_name columns of the sales.customer table.

It separates the last name and first name by the comma (,) and space.

SELECT 
    first_name, 
    last_name, 
    CONCAT_WS(', ', last_name, first_name) full_name
FROM 
    sales.customers
ORDER BY 
    first_name, 
    last_name;

Use CONCAT_WS() Function with NULL

The following statement indicates how the CONCAT_WS() function handles input strings that have NULL values.

SELECT 
    CONCAT_WS(',', 1, 2, NULL, NULL, 3);

The output is as follows:

result
----------------------------------------
1,2,3
 
(1 row affected)

As you can see from the above output, the CONCAT_WS() function ignores NULL and don’t add the separator between the NULL values.

The following example concatenates the customer data to format customer’s addresses. If the customer does not have a phone number, that function ignores it.

SELECT 
    CONCAT_WS
    (
        CHAR(13), 
        CONCAT(first_name, ' ', last_name), 
        phone, 
        CONCAT(city, ' ', state), 
        zip_code,
        '---'
    ) customer_address
FROM 
    sales.customers
ORDER BY 
    first_name, 
    last_name;

Using CONCAT_WS() to generate CSV file

This statement uses the comma (,) as a separator and concatenates values in the first_name, last_name, and email column to generate the CSV file.

See the following query.

SELECT 
    CONCAT_WS(',', first_name, last_name, email)
FROM 
    sales.customers
ORDER BY 
    first_name, 
    last_name;

So, In this tutorial, you have learned how to use the SQL CONCAT_WS() function to concatenate strings with a separator.

Finally, SQL CONCAT_WS Function Example is over.

Recommended Posts

SQL DIFFERENCE Function Example

SQL LIKE Operator Tutorial With Example

Understand SQL Constraints

SQL Operators Tutorial With Example

SQL Except Clause Example

The post SQL CONCAT_WS Function Example | CONCAT_WS Method In SQL appeared first on AppDividend.

Java.lang.Boolean Class In Java Example From Scratch

$
0
0
Java.lang.Boolean Class In Java Example From Scratch

Java.lang.Boolean Class In Java Example From Scratch is today’s topic. Java.lang.Boolean class wraps are used for wrapping the value of primitive data type, i.e. boolean in an object. This boolean class contains two values, i.e. true or false. Java provides a wrapper class Boolean in java.lang package. The Boolean class wraps a value of the primitive type boolean in an object. An object of type Boolean contains a single field, whose type is boolean.

Java.lang.Boolean Class In Java

The Boolean class simply a wrapper class for the primitive type boolean. It wraps the boolean primitive value to an object. An object of type Boolean contains a single field whose type is boolean.

The syntax for creating a boolean object.

Boolean y = new Boolean(boolean arg);

In the above syntax, we have created a boolean object which contains arg as a value.

Boolean y = new Boolean(String str);

The above syntax is true if the string is not null and is equal, and in this, we can ignore the case otherwise false.

Field:

  1. static Boolean FALSE-  This boolean object contains the value of primitive data as false.
  2. Static Boolean TRUE- This boolean object contains the value of primitive data as true.
  3. Static Class<Boolean> TYPE- It is the class object of primitive type boolean.

Methods of Java.lang.Boolean:

static boolean parseBoolean(String str):

This method returns the string argument as a boolean. The method will return true if the string is not null and is equal, and in this, we can ignore the case; otherwise, it returns false if it is not matched.

See the following syntax.

public static boolean parseBoolean(String str) {}

See the program.

public class demo {
    public static void main(String args[]) {
        boolean a = Boolean.parseBoolean("False");
        boolean b = Boolean.parseBoolean("True");
        boolean c = Boolean.parseBoolean("faLsE");
        boolean d = Boolean.parseBoolean("AppDividend");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
        System.out.println(d);
    }
}

See the output.

 

Java.lang.Boolean Class In Java

boolean booleanValue():

This method only returns the value of the boolean object as boolean.

Syntax:

public boolean booleanValue()

See the following Java program.

public class demo {
    public static void main(String args[]) {
        Boolean a = new Boolean("false");
        boolean a1 = a.booleanValue(); // getting the value
        Boolean b = new Boolean("True");
        boolean b1 = b.booleanValue(); // getting the value
        Boolean c = new Boolean("Appdividend");
        boolean c1 = c.booleanValue(); // getting the value

        System.out.println(a1);
        System.out.println(b1);
        System.out.println(c1);
    }
}

See the following output.

 

boolean booleanValue()

static Boolean valueOf(boolean a):

This method returns a boolean object containing a boolean value.

Syntax:

public static boolean valueOf(boolean a);

See the following program.

public class demo {
    public static void main(String[] args) {
        boolean a = true;
        boolean b = false;
        Boolean a1 = Boolean.valueOf(a);
        Boolean b1 = Boolean.valueOf(b);
        System.out.println(a1);
        System.out.println(b1);
    }
}

See the following output.

 

static Boolean valueOf(boolean a)

Static Boolean valueOf(String s):

This method returns a Boolean output with a value represented by the string ‘s’. It returns true only if the string argument is not null and is equal, ignoring the case. It returns false when the string is not equal.

See the following syntax.

public static boolean valueOf(String s)

See the following program.

public class demo {
    public static void main(String args[]) {
        Boolean a = Boolean.valueOf("tRue");
        Boolean b = Boolean.valueOf("false");
        Boolean c = Boolean.valueOf("null");
        System.out.println(a);
        System.out.println(b);
        System.out.println(c);
    }
}

See the output.

 

static Boolean valueOf(String s)

Static String toString(boolean b):

It returns the string representing a specific boolean. In this, if the string is true, it will return true otherwise false. See the following syntax.

public static String toString(boolean b)

See the following program.

public class demo {
    public static void main(String args[]) {
        boolean a = true;
        boolean b = false;
        String a1 = Boolean.toString(a);
        String b2 = Boolean.toString(b);
        System.out.println(a1);
        System.out.println(b2);
    }
}

See the output.

 

static String toString(boolean b)

String toString()

It returns a string object representing a boolean value. It returns true if the string is equal to “true,” otherwise false is returned.

See the following program.

public class demo {
    public static void main(String args[]) {
        Boolean a = new Boolean("True");
        Boolean b = new Boolean("False");
        String str1 = a.toString();
        String str2 = b.toString();
        System.out.println(str1);
        System.out.println(str2);
    }
}

See the output.

 

String toString()

int hashCode

This method returns a hash code for the boolean instance. The hash code is fixed here, for true it’s 1231, and for false it’s 1237.

See the following syntax.

public int hashCode()

See the following program.

public class demo {
    public static void main(String[] args) {
        Boolean a = new Boolean("True");
        Boolean b = new Boolean("false");
        Boolean c = new Boolean("TRue");

        System.out.println(a.hashCode());
        System.out.println(b.hashCode());
        System.out.println(c.hashCode());
    }
}

See the output.

 

int hashCode

boolean equals(Object ob):

It returns true only if the boolean object represents the same value; otherwise false.

See the following syntax.

public boolean equals(Object ob)

See the following program.

public class demo {
    public static void main(String args[]) {
        Boolean a = new Boolean("True");
        Boolean b = new Boolean("False");
        Boolean c = new Boolean(null);
        System.out.println(a.equals(b));
        System.out.println(b.equals(b));
        System.out.println(c.equals(a));
    }
}

See the output.

 

boolean equals(Object ob)

int compareTo(Boolean b):

It compares the present boolean object with the passed argument b.

See the following syntax.

public int compareTo(Boolean b)

The function returns the following output:

  1. Zero when object matches with the argument value.
  2. A positive value when the object represents true, whereas the argument represents false value.
  3. A negative value when the object represents false, whereas the argument represents true.

See the following program.

public class demo {
    public static void main(String args[]) {
        Boolean a = new Boolean("True");
        Boolean b = new Boolean("False");
        Boolean c = new Boolean("TRue");

        System.out.println(b1.compareTo(b));
        System.out.println(b1.compareTo(c));
        System.out.println(b2.compareTo(a));
    }
}

See the output.

 

int compareTo(Boolean b)

int compare(boolean x, boolean y):

It is used to compare the primitive boolean variables like if x is true and y is false, the output is positive.

See the following syntax.

public static int compare(boolean x, boolean y)

It returns zero when x and y have the same value as true-true or false-false and positive when x->true and y->false.

See the following program.

public class demo {
    public static void main(String args[]) {
        boolean a = true;
        boolean b = false;
        boolean c = true;
        System.out.println(Boolean.compare(a, b));
        System.out.println(Boolean.compare(a, c));
        System.out.println(Boolean.compare(b, c));
    }
}

See the output.

int compare(boolean x, boolean y)

 

Finally, Java.lang.Boolean Class In Java Example From Scratch is over.

Recommended Posts

Java StringBuilder Class

Java Comparable Interface Tutorial

Java Packages Tutorial With Example

Method Overriding in Java Tutorial

Java Assertion Tutorial

The post Java.lang.Boolean Class In Java Example From Scratch appeared first on AppDividend.

How to Map MySQL’s TINYINT(1) to Boolean in jOOQ

$
0
0

MySQL 8 does not yet support the BOOLEAN type as specified in the SQL standard. There is a DDL “type” called BOOL, which is just an alias for TINYINT:

create table t(b bool);

select 
  table_name, 
  column_name, 
  data_type, 
  column_type
from information_schema.columns
where table_name = 't';

The above produces:

TABLE_NAME|COLUMN_NAME|DATA_TYPE|COLUMN_TYPE|
----------|-----------|---------|-----------|
t         |b          |tinyint  |tinyint(1) |

Notice that BOOL translates to a specific “type” of TINYINT, a TINYINT(1), where we might be inclined to believe that the (1) corresponds to some sort of precision, as with NUMERIC types.

However, counter intuitively, that is not the case. It corresponds to the display width of the type, when fetching it, using some deprecated modes. Consider:

insert into t(b) values (0), (1), (10);
select * from t;

We’re getting:

b |
--|
 0|
 1|
10|

Notice also that MySQL can process non-boolean types as booleans. Running the following statement:

select * from t where b;

We’re getting:

b |
--|
 1|
10|

Using this column as a Boolean column in jOOQ

By default, jOOQ doesn’t recognise such TINYINT(1) columns as boolean columns, because it is totally possible that a user has created such a column without thinking of boolean types, as the above example has shown.

In previous versions of jOOQ, the data type rewriting feature could be used on arbitrary expressions that match the boolean column name, e.g. the below would treat all columns named "B" as BOOLEAN:

<forcedTypes>
  <forcedType>
    <name>BOOLEAN</name>
    <includeExpression>B</includeExpression>
  </forcedType>
</forcedTypes>

With jOOQ 3.12.0 (issue #7719), we can now match this display width as well for MySQL types. That way, you can write this single data type rewriting configuration to treat all integer types of display width 1 as booleans:

<forcedTypes>
  <forcedType>
    <name>BOOLEAN</name>
    <includeTypes>(?i:TINYINT\(1\))</includeTypes>
  </forcedType>
</forcedTypes>

Using this configuration in the code generator, the above query:

select * from t where b;

… can now be written as follows, in jOOQ

selectFrom(T).where(T.B).fetch();

Putting Galera SST Compression on the benchmark

$
0
0

I mentioned in my Galera crash (un)safe post that it’s bad if a SST is triggered on a large dataset. On a Galera node an SST will simply wipe the contents of the MySQL data directory and copy a snapshot from another node in the cluster. For consistency this is a favorable thing to do, but from an HA perspective it isn’t: one node in the cluster is unavailable and another one is acting as donor. This means, if you have a three node Galera cluster, only two are available where one has “degraded” performance.

This could have quite high impact, for instance in the proxysql_galera_checker script only synced nodes are selected to receive traffic. By default the donor nodes will not receive any traffic and now the cluster only has one node left to serve traffic. Don’t worry: if there are no synced nodes available the donor node will still be selected as available, so in the case you only have one node left (bootstrapping) it can still serve traffic. This, obviously, isn’t a favorable situation you want to be in.

Partial failure on Galera

Now imagine we have a multi DC Galera cluster, as pictured below:

galera-multi-dc-small

A power failure happens in DC #1 and nodes 1 to 3 are all gone. As the nodes in DC #2 are not a majority anymore, the nodes shut down out of safety. As I wrote before in the Galera crash (un)safe blog post: a crash unsafe Galera cluster will force SST to happen on crashed nodes and this happened as well in our case of the nodes in DC #1. The most favorable node to recover from is a cleanly shut down node in DC #2.

The bootstrap cluster automation performing the recovery of the cluster ran in sequential order through its configured hosts. Unfortunately the first node in the list was an unclean node in DC #1, forcing SST to happen on this host. If the other host in DC #2 would have been chosen, a simple IST would have sufficed and the second node in the cluster would have been brought up within minutes. Now the automation was waiting for the SST on the node in DC #1 and this caused a delay of 4 hours for the next node in the automation to be brought up.

Painful GCache durability

Durability of the GCache on a Galera node is calculated by looking up the first and last item in the ringbuffer and then calculate the time between the two. A Galera incremental state transfer (IST) can only happen if the delta of the writeset requested by the joining node is present in the GCache on the donor node. This durability is basically the time you are allowed to perform an IST from this node and this metric is one of the ones to keep an eye upon. Our GCache durability was somewhere in the range of 45 minutes.

When binary logging is set to row based replication and binlog_row_image is set to full (default), the data written to the binlog will contain the previous row state and the updated values. The same applies to the GCache ringbuffer: when set to full the entire previous state of the row will be written to the GCache.

On this particular cluster one of the tables looked similar to this:

CREATE TABLE product (
  pid BIGINT NOT NULL AUTO INCREMENT,
  title varchar(255) NOT NULL,
  description TEXT NOT NULL,
  specifications TEXT NOT NULL,
  stock INT NOT NULL DEFAULT 0,
  price INT NOT NULL DEFAULT 0,
  image_1 VARCHAR(255) NOT NULL,
  image_2 VARCHAR(255) NOT NULL,
  image_3 VARCHAR(255) NOT NULL,
  thumbnail_1 VARCHAR(255) NOT NULL,
  thumbnail_2 VARCHAR(255) NOT NULL,
  thumbnail_3 VARCHAR(255) NOT NULL,
  ...
  another 50+ columns
  ...
PRIMARY KEY(pid)) ENGINE=InnoDB;

You might think a SST isn’t a big deal, but if you have a data size of 1TB it will take about 3 hours to transfer on a 1Gb network or, if you’re lucky, 21 minutes on a 10Gb network. The connection between DC #1 and #2 was a VPN that was limited in bandwidth (about 400Mbps) and moving the 400GB snapshot between node 4 and node 1 took about 4 hours to complete.

As the bootstrapped node was online according to the ProxySQL script, it now allowed writes to the cluster while being a donor node. The mass-update jobs (stock and pricing sync) started to run once again altering all sorts of data inside the cluster. This means a SST taking 4 hours to complete would make IST impossible between the cleanly shut down nodes in DC #2! As a result inside DC #2 the SST will also happen between nodes 4 and 5. Luckily the local network in DC #2 is a bit faster than the VPN but it was a totally unnecessary recovery.

Recovery improvements

If we look at the outage, the cluster was unavailable for a few minutes thanks to ProxySQL sending all traffic to a single node. But according to the definition of high availability, a single node is not HA. So if we take into account that we need at least two nodes to be available, the recovery happens only after the first SST has completed. This means our Mean Time To Recover Service (MTTRS) on Galera was at least 4 hours!

MTTR-Galera-flow

But as explained earlier: the ProxySQL script will not allow traffic to be sent to a donor, unless there is no other node available. This means right after node 1 has been recovered the ProxySQL script will remove the bootstrapped node 4 from available nodes and we’re back to one single node availability. Technically then the MTTRS should be extended till after node 2 has been recovered. But we’ll keep this discussion out of the scope for now.

In the post mortem of this incident we identified a couple of improvements we could make to speed up the recovery of a Galera cluster:

  1. Faster network (between DC #1 and DC #2)
  2. Make GCache bigger
  3. Increase GCache durability
  4. Make the transfer smaller

The first option was not feasible as it would increase cost dramatically, so we focused on option 2 and 3 at first. The GCache was already set to 4GB, which is already quite large. So we simply changed the binlog_row_image parameter from full to minimal. Since most modifications per row were only a few bytes this increased the durability from 45 minutes to somewhere between of 4 to 5 days! I felt a lot more confident that unnecessary SSTs wouldn’t happen anymore.

How to make a Galera State Snapshot Transfer smaller?

Now the fourth option proved to be a bit more challenging: how to decrease the data size of 400GB? We could just drop a couple of the tables larger than 50GB, but I think the product managers would be very angry at me. Another option would be to enable table compression, but I rather not go through the slow migration process on tables larger than 50GB with distributed storage on a hyperconverged infrastructure

Another option is to compress during the creation of the xtrabackup snapshot and this is done for example by using the following configuration:

[sst]
compressor="gzip"
decompressor="gzip -dc"

This would save us probably something near half of the bytes to send over the line, and every byte compressed means we can send the SST faster, right? Naturally we wanted to test this and benchmark how much faster we would be able to move data between the two locations than our current uncompressed SST.

Benchmarking State Snapshot Transfers

We selected the following methods:

  1. Uncompressed
  2. Gzip
  3. Pigz (normal and fast)
  4. LZ4
  5. Snappy
  6. Qpress (LZH built in xtrabackup)

The method for testing was limit the bandwidth between two nodes in our Galera test cluster (4 cores and 8GB of memory) to 300Mbit, force SST to happen on one node and then measure the time between the SST to start and the moment when the node has rejoined the cluster. The amount of bytes transferred was measured through the network interface and we re-ran each method three times to get a reliable outcome.

First of all the throughput tells us already a couple of things:

Galera SST benchmark network throughput

Galera SST benchmark network throughput

LZ4 and Snappy seem to be able to almost fully utilize the bandwidth of our test system, which is good.

We can see the throughput of gzip and pigz is very low. Gzip is renowned for being slow in the compression phase, but pigz (parallel gzip) is supposed to tackle this by allowing parallel execution of chunks of data. On the test machine the graphs of the gzip run were showing it actually was limited by the single core being utilized fully:

Benchmark SST donor GZIP (second set of peaks)

Benchmark SST donor GZIP (second set of peaks)

The peaks before the gzip runs are the uncompressed runs. Throughput really is dwarfed by the uncompressed run.

You may think pigz is any better, but alas even in fast compression mode it’s not much better:

Benchmark SST donor PIGZ fast compression (last three peaks)

Benchmark SST donor PIGZ fast compression (last three peaks)

Yes it will compresses now on all four cores, but the throughput is only twice as much.

So what about the total amount of bytes transferred?

Galera SST benchmark - total bytes transferred

Galera SST benchmark – total bytes transferred

Gzip and pigz are truly king (and queen) here: they save almost 60% of total bytes transferred! This is an amazing achievement and it saves a lot of network bandwidth. LZ4 and Snappy do a much worse job at 25% and 32% respectively.

Now the most important graph, the total duration that we were after:

Galera SST benchmark - total duration

Galera SST benchmark – total duration

LZ4 and Snappy are clear winners here by saving us 15% and 11% in duration of the SST.

Conclusion

We applied Snappy to our production Galera cluster. As our production servers were slightly different we were able to save about 20% on the duration of the state snapshot transfer.

I think the outcome would also be a bit more favorable for pigz on these production servers as they ran on 8 cores instead of only 4 cores. However I fear for the responsiveness of a bootstrapped server utilizing all 8 cores to the maximum for a few hours. Snappy and LZ4 may compress a bit less, but they are much “friendlier” to your donor.

And the final advice I can give you is to keep an eye on the GCache durability as this may be a life saver one day!

Want more?

This is one of the background stories of my talk Benchmarking Should Never Be Optional on Wednesday 2nd of October 2019 at Percona Live Europe in Amsterdam.

See me speak at Percona Live Europe 2019

In my talk I will feature a few cases why you should always benchmark your systems up front. It’s not only about database benchmarking, but in some cases even the entire system that requires benchmarking.

Multiplexing (Mux) in ProxySQL: Use Case

$
0
0
Multiplexing (Mux) in ProxySQL

Multiplexing (Mux) in ProxySQLMultiplexing Background

Historically it’s a technique used in networking to integrate multiple analog and digital signals via a shared medium. The goal of multiplexing over the network was to enable signals to be transmitted more efficiently for a given communication channel, thus achieving cost efficiency. 

Since the term Multiplexing comes from telecommunications, the industry has heavily used a device called Multiplexers – aka Mux. There was even a term called muxing where signals were often analog and digital to be combined in a single line. 

The technique was developed in the early 1870s, it’s origins to be found in telegraphy, and it has become a standard for digital telecommunications in the 20th Century. 

Following multiplexing methods are currently available: 

  • Frequency Division Multiplexing (FDM)
  • Time Division Multiplexing (TDM)
  • Wavelength Division Multiplexing (WDM)

There’s the other way in telco that we aren’t going to get into too much, which is called demultiplexer. Demux involves reanalyzing composite signals to separate them. 

How can we achieve Multiplexing for MySQL database connections?

We would basically need a Mux between the database and the application server. This means a proxy layer that can combine communication channels to the backend database. Again the goal is to reduce the overhead of opening several connections and maintaining a minimal number of open connections to reduce memory footprint. 

Thread pooling is available in the following MySQL distributions:

  • MySQL Enterprise Edition 
  • Percona Server 
  • MariaDB 

The way they work is the listener accepts the connections and hands it over to a group of thread pools. This way each client connection is handled by the same thread pool. The above implementations aren’t as efficient as ProxySQL’s implementation. 

ProxySQL comes to help when we need to Mux our communication channels to a database server, where it can often be flooded.

Main Use Cases

  • Any application with a persistent connection to the database
  • Java applications to be specific with built-in connection pools

Goals to Achieve 

  • Reduce connections similar to Aurora
  • Reduce huge number of connections from hardware 
  • Reduce context switching
  • Reduce mutex/contention 
  • Reduce CPU cache usage

ProxySQL Technique Used:

Threading Models 

  • One thread per connection
    • Easier to develop
    • Blocking I/O
  • Thread Pooling
    • Non-blocking I/O
    • Scalable architecture

Here’s what we can control using ProxySQL

Pros

  • Reduced number of connections and overhead to the backend database  
  • Control over database connections
  • Collect metrics of all database connections and monitor 
  • Can be enabled and disabled. 

Cons

  • Certain conditions and limitations apply to use
  • Can cause unexpected behavior to application logic. 

How it works:  

Ad-hoc enable/disable of multiplexing

mysql_query_rules.multiplexing allows to enable or disable multiplexing based on matching criteria. 

The field currently accepts these values:

  • 0: disable multiplex
  • 1: enable multiplex
  • 2: do not disable multiplex for this specific query containing @

Also, ProxySQL has some default behavior that can lead to unexpected results. In fact, ProxySQL can disable on purpose the multiplexing on a connection in the following cases:

  • When a transaction is active
  • When you issued commands like LOCK TABLE, GET_LOCK() and others
  • When you created a temporary table using CREATE TEMPORARY TABLE
  • When you used in the query session or user variables starting the @ symbol

In the majority of cases, ProxySQL can return the connection to the pool enabling the multiplexing. But only in the last case, when using session and user variables starting with @, the connections never return to the pool.

In a recent investigation on one of our client’s systems, we discovered a high amount of connections and threads used, despite the ProxySQL layer. The problem was related to queries containing the @ symbol in the Java connector when establishing a new connection. In a matter of seconds after enabling it, the multiplexing was disabled for all the connections. The effect is having no multiplexing at all: for example, 2000 connections from the front ends were reflected on the same number of connections to the back ends. We needed a way to avoid automatic disabling of multiplexing.  

How to find on ProxySQL stats all the executed queries containing the @ symbol:

SELECT DISTINCT digest, digest_text FROM stats_mysql_query_digest WHERE digest_text LIKE '%@%';
*************************** 1. row ***************************
digest_text: select @@version_comment limit ?
*************************** 2. row ***************************
digest_text: SELECT @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@collation_server AS collation_server, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_buffer_length AS net_buffer_length, @@net_write_timeout AS net_write_timeout, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@tx_isolation AS tx_isolation, @@wait_timeout AS wait_timeout
*************************** 3. row ***************************
digest_text: SELECT @@session.auto_increment_increment AS auto_increment_increment, @@character_set_client AS character_set_client, @@character_set_connection AS character_set_connection, @@character_set_results AS character_set_results, @@character_set_server AS character_set_server, @@init_connect AS init_connect, @@interactive_timeout AS interactive_timeout, @@license AS license, @@lower_case_table_names AS lower_case_table_names, @@max_allowed_packet AS max_allowed_packet, @@net_buffer_length AS net_buffer_length, @@net_write_timeout AS net_write_timeout, @@query_cache_size AS query_cache_size, @@query_cache_type AS query_cache_type, @@sql_mode AS sql_mode, @@system_time_zone AS system_time_zone, @@time_zone AS time_zone, @@tx_isolation AS tx_isolation, @@wait_timeout AS wait_timeout

To create rules on ProxySQL:

INSERT INTO mysql_query_rules(active,digest,multiplex,apply) SELECT DISTINCT 1,digest,2,0 FROM stats_mysql_query_digest WHERE digest_text LIKE '%@%';

LOAD MYSQL QUERY RULES TO RUNTIME;

SAVE MYSQL QUERY RULES TO DISK;

And the result revealed huge savings over connections and thread pool directly captured from PMM.

Conclusion

In conclusion, ProxySQL’s multiplexing feature is something every high traffic site would benefit from. What we always observe is a lower number of connections to the backend lowers the overhead of both memory utilization and context switching. In order to fully benefit multiplexing, be aware of the above limitations and investigate connection types even after implementing. 

References 

https://www.allaboutcircuits.com/technical-articles/an-intro-to-multiplexing-basis-of-telecommunications/

https://www.techopedia.com/definition/8472/multiplexing

Understanding Multiplexing in Telecommunications

https://medium.com/searce/reduce-mysql-memory-utilization-with-proxysql-multiplexing-cbe09da7921c

https://en.wikipedia.org/wiki/Multiplexing

Thanks for their valuable input :

  • Rene Cannao
  • Marco Tusa
  • Daniel Guzman Burgos
  • Corrado Pandiani
  • Tom De Comman

The AnomeMultiplexing diagram, modified, CC BY-SA 3.0

Viewing all 18830 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>