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

Meet Galera Cluster at Percona Live Europe 2019 (Amsterdam)

$
0
0

We (Codership, the original and continued developers and experts of Galera Cluster) participated in Austin 2019, and so it would have seemed remiss if we did not also show up at the Percona Live Open Source Database Conference Europe 2019 (that was a mouthful!) happening in Amsterdam September 30 – October 2 2019. We have a booth in the expo hall at the Hilton Amsterdam Schipol Airport, so come drop by and say hello!

 

While we do not have any talks accepted in the main program, we do have a tutorial that involves using Galera Cluster and MariaDB Server on the first day at 9am by Colin Charles.  View the whole agenda and you will also see other Galera Cluster related talks naturally.

 

Meet us at Galera Cluster booth.  We’d like to talk to you about what you need from Galera Cluster, roadmaps, plans, how you use Percona XtraDB Cluster (PXC) based on Galera Cluster, and more. We’ll have some great conversations, and a whole bunch more planned for the conference.  Don’t forget that we have great support and consulting services too, so come talk to us to find out more!

 


Percona XtraDB Cluster 5.6.45-28.36 Is Now Available

$
0
0
Percona XtraDB Cluster

Percona XtraDB Cluster

Percona is glad to announce the release of Percona XtraDB Cluster 5.6.45-28.36 on September 17, 2019. Binaries are available from the downloads section or from our software repositories.

Percona XtraDB Cluster 5.6.45-28.36 is now the current release, based on the following:

All Percona software is open-source and free.

Bugs Fixed

  • PXC-2432: PXC was not updating the information schema user/client statistics properly.
  • PXC-2555: SST initialization delay: fixed a bug where the SST process took too long to detect if a child process was running.

Help us improve our software quality by reporting any bugs you encounter using our bug tracking system. As always, thanks for your continued support of Percona!

How to Install Bolt CMS with Nginx and Let's Encrypt on FreeBSD 12

$
0
0
Bolt is a sophisticated, lightweight and simple CMS built with PHP. This tutorial shows the installation of Bolt CMS in FreeBSD 12 with Nginx web server, MySQL database server and Let's Encrypt SSL certificate.

Percona XtraDB Cluster 5.7.27-31.39 Is Now Available

$
0
0
Percona XtraDB Cluster

Percona XtraDB ClusterPercona is happy to announce the release of Percona XtraDB Cluster 5.7.27-31.39 on September 18, 2019. Binaries are available from the downloads section or from our software repositories.

Percona XtraDB Cluster 5.7.27-31.39 is now the current release, based on the following:

All Percona software is open-source and free.

Bugs Fixed

  • PXC-2432: PXC was not updating the information_schema user/client statistics properly.
  • PXC-2555: SST initialization delay: fixed a bug where the SST process took too long to detect if a child process was running.
  • PXC-2557: Fixed a crash when a node goes NON-PRIMARY and SHOW STATUS is executed.
  • PXC-2592: PXC restarting automatically on data inconsistency.
  • PXC-2605: PXC could crash when log_slow_verbosity included InnoDB.  Fixed upstream PS-5820.
  • PXC-2639: Fixed an issue where a SQL admin command (like OPTIMIZE) could cause a deadlock.

Help us improve our software quality by reporting any bugs you encounter using our bug tracking system. As always, thanks for your continued support of Percona!

Achieving MySQL Failover & Failback on Google Cloud Platform (GCP)

$
0
0

There are numerous cloud providers these days. They can be small or large, local or with data centers spread across the whole world. Many of these cloud providers offer some kind of a managed relational database solution. The databases supported tend to be MySQL or PostgreSQL or some other flavor of relational database. 

When designing any kind of database infrastructure it is important to understand your business needs and decide what kind of availability you would need to achieve. 

In this blog post, we will look into high availability options for MySQL-based solutions from one of the largest cloud providers - Google Cloud Platform.

Deploying a Highly Available Environment Using GCP SQL Instance

For this blog we want is a very simple environment - one database, with maybe one or two replicas. We want to be able to failover easily and restore operations as soon as possible if the master fails. We will use MySQL 5.7 as the version of choice and start with the instance deployment wizard:

We then have to create the root password, set the instance name, and determine where it should be located:

Next, we will look into the configuration options:

We can make changes in terms of the instance size (we will go with db-n1-standard-4), storage,  and maintenance schedule. What is most important for us in this setup are the high availability options:

Here we can choose to have a failover replica created. This replica will be promoted to a master should the original master fail.

After we deploy the setup, let’s add a replication slave:

Once the process of adding the replica is done, we are ready for some tests. We are going to run test workload using Sysbench on our master, failover replica, and read replica to see how this will work out. We will run three instances of Sysbench, using the endpoints for all three types of nodes.

Then we will trigger the manual failover via the UI:

Testing MySQL Failover on Google Cloud Platform?

I have got to this point without any detailed knowledge of how the SQL nodes in GCP work. I did have some expectations, however, based on previous MySQL experience and what I’ve seen in the other cloud providers. For starters, the failover to the failover node should be very quick. What we would like is to keep the replication slaves available, without the need for a rebuild. We would also like to see how fast we can execute the failover a second time (as it is not uncommon that the issue propagates from one database to another).

What we determined during our tests...

  1. While failing over, the master became available again in 75 - 80 seconds.
  2. Failover replica was not available for 5-6 minutes.
  3. Read replica was available during the failover process, but it became unavailable for 55 - 60 seconds after the failover replica became available

What we’re not sure about...

What is happening when the failover replica is not available? Based on the time, it looks like the failover replica is being rebuilt. This makes sense, but then the recovery time would be strongly related to the size of the instance (especially I/O performance) and the size of the data file.

What is happening with read replica after the failover replica would have been rebuilt? Originally, the read replica was connected to the master. When the master failed, we would expect the read replica to provide an outdated view of the dataset. Once the new master shows up, it should reconnect via replication to the instance (which used to be failover replica and which has been promoted to master). There is no need for a minute of downtime when CHANGE MASTER is being executed.

More importantly, during the failover process there is no way to execute another failover (which sort of makes sense):

It is also not possible to promote read replica (which not necessarily makes sense - we would expect to be able to promote read replicas at any time).

It is important to note, relying on the read replicas to provide high availability (without creating a failover replica) is not a viable solution. You can promote a read replica to become a master, however a new cluster would be created; detached from the rest of the nodes.

There is no way to slave your other replicas off the new cluster. The only way to do this would be to create new replicas, but this is a time-consuming process. It is also virtually non-usable, making the failover replica to be the only real option for high availability for SQL nodes in Google Cloud Platform.

Conclusion

While it is possible to create a highly-available environment for SQL nodes in GCP, the master will not be available for roughly a minute and a half. The whole process (including rebuilding the failover replica and some actions on the read replicas) took several minutes. During that time we weren’t able to trigger an additional failover, nor we we able to promote a read replica. 

Do we have any GCP users out there? How are you achieving high availability?

 

Create MySQL Test Instance with Oracle Cloud Free Tier

$
0
0

Oracle announced this week at Oracle OpenWorld that it has introduced a new cloud offer called Oracle Cloud Free Tier. As the name suggest, it allows you to run a few limited instances in Oracle Cloud for free. I will in this blog show how you can use the free tier to setup a MySQL test instance.

Tip

If you want to read more about Oracle Cloud Free Tier see https://www.oracle.com/cloud/free/ and the FAQ at https://www.oracle.com/cloud/free/faq.html.

The first step is to sign up for the cloud service which you do by opening https://www.oracle.com/cloud/free/ and click on the Start for free button near the top of the page:

Click on Start for free to get started

This will take you through a series of pages where you create your Oracle Cloud account. The steps are straight forward. You will need to provide a valid mobile number and credit card (but no fees are charges provided you stick to the always free services). At the end you are directed to the Oracle Cloud login page:

Oracle Cloud Login Screen
Oracle Cloud Login Screen

Enter the email address and password from the registration process, and you are ready to use create Oracle Cloud services. You will need a compute instance which you create by choosing the Compute Create a VM Instance quick action:

The Oracle Cloud front page after logging in the first time

Notice how there is a label Always Free Eligible which tells you can create instances in the free tier.

On the next screen, you can fill in the details for the instance. You can choose all the default values which will create a VM.Standard.E2.1.Micro virtual machine which is one of the shapes that are included in the free tier. The shape includes 1 OCPU (1 CPU with hyperthreading, so two virtual CPUs) and 1GiB of memory. It will also set everything up for you including the network with ssh access.

To be able to ssh to the instance, you need to add the public ssh key for your ssh key pair. If you do not already have an ssh key, then https://docs.oracle.com/en/cloud/paas/event-hub-cloud/admin-guide/generate-ssh-key-pair-using-puttygen.html has an example of creating one on Microsoft Windows.

Once you click create, a workflow is created and launched. While the workflow is running, the icon in the top left corner is yellow/orange to indicate that the instance is being worked on. Once the workflow has completed, the instance is available and the icon turns green.

You will need the Public IP Address which you can find in the Primary VNIC Information section when viewing the instance details:

With that and your ssh key, you can connect to the instance using the opc user, for example (this assumes you have the private key in OpenSSH format):

shell$ ssh -i ~/.ssh/id_rsa opc@<ip address of vm>

The first step to install MySQL is to install the MySQL yum repository:

[opc@mysql ~]$ sudo yum install https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpmLoaded plugins: langpacks, ulninfo                                                                  
mysql80-community-release-el7-3.noarch.rpm                                    |  25 kB  00:00:00     
Examining /var/tmp/yum-root-4Yk8Ev/mysql80-community-release-el7-3.noarch.rpm: mysql80-community-release-el7-3.noarch                                                                                     
Marking /var/tmp/yum-root-4Yk8Ev/mysql80-community-release-el7-3.noarch.rpm to be installed          
Resolving Dependencies                                                                               
--> Running transaction check                                                                        
---> Package mysql80-community-release.noarch 0:el7-3 will be installed                              
--> Finished Dependency Resolution

Dependencies Resolved

=====================================================================================================
 Package                      Arch      Version     Repository                                  Size
=====================================================================================================
Installing:
 mysql80-community-release    noarch    el7-3       /mysql80-community-release-el7-3.noarch     31 k

Transaction Summary
=====================================================================================================
Install  1 Package

Total size: 31 k
Installed size: 31 k
Is this ok [y/d/N]: y
Downloading packages:
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
  Installing : mysql80-community-release-el7-3.noarch                                            1/1
  Verifying  : mysql80-community-release-el7-3.noarch                                            1/1

Installed:
  mysql80-community-release.noarch 0:el7-3

Complete!

Now you can install any of the MySQL products using the yum command. For example, to install MySQL Server, the MySQL client programs, and MySQL Shell:

[opc@mysql ~]$ sudo yum install mysql-community-server mysql-community-client mysql-shell
Loaded plugins: langpacks, ulninfo                                                       
Resolving Dependencies                                                                   
--> Running transaction check                                                            
---> Package mysql-community-client.x86_64 0:8.0.17-1.el7 will be installed              
--> Processing Dependency: mysql-community-libs(x86-64) >= 8.0.11 for package: mysql-community-client-8.0.17-1.el7.x86_64                                                                                 
---> Package mysql-community-server.x86_64 0:8.0.17-1.el7 will be installed                          
--> Processing Dependency: mysql-community-common(x86-64) = 8.0.17-1.el7 for package: mysql-community-server-8.0.17-1.el7.x86_64                                                                          
---> Package mysql-shell.x86_64 0:8.0.17-1.el7 will be installed                                     
--> Running transaction check                                                                        
---> Package mariadb-libs.x86_64 1:5.5.64-1.el7 will be obsoleted                                    
--> Processing Dependency: libmysqlclient.so.18()(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64  
--> Processing Dependency: libmysqlclient.so.18(libmysqlclient_18)(64bit) for package: 2:postfix-2.10.1-7.el7.x86_64                                                                                      
---> Package mysql-community-common.x86_64 0:8.0.17-1.el7 will be installed                          
---> Package mysql-community-libs.x86_64 0:8.0.17-1.el7 will be obsoleting                           
--> Running transaction check                                                                        
---> Package mysql-community-libs-compat.x86_64 0:8.0.17-1.el7 will be obsoleting                    
--> Finished Dependency Resolution                                                                   

Dependencies Resolved

=====================================================================================================
 Package                           Arch         Version            Repository                   Size 
=====================================================================================================
Installing:                                                                                          
 mysql-community-client            x86_64       8.0.17-1.el7       mysql80-community            32 M 
 mysql-community-libs              x86_64       8.0.17-1.el7       mysql80-community           3.0 M 
     replacing  mariadb-libs.x86_64 1:5.5.64-1.el7                                                   
 mysql-community-libs-compat       x86_64       8.0.17-1.el7       mysql80-community           2.1 M 
     replacing  mariadb-libs.x86_64 1:5.5.64-1.el7                                                   
 mysql-community-server            x86_64       8.0.17-1.el7       mysql80-community           415 M 
 mysql-shell                       x86_64       8.0.17-1.el7       mysql-tools-community        15 M 
Installing for dependencies:                                                                         
 mysql-community-common            x86_64       8.0.17-1.el7       mysql80-community           589 k 

Transaction Summary
=====================================================================================================
Install  5 Packages (+1 Dependent package)                                                           

Total download size: 468 M
Is this ok [y/d/N]: y     
Downloading packages:     
warning: /var/cache/yum/x86_64/7Server/mysql80-community/packages/mysql-community-common-8.0.17-1.el7.x86_64.rpm: Header V3 DSA/SHA1 Signature, key ID 5072e1f5: NOKEY                                    
Public key for mysql-community-common-8.0.17-1.el7.x86_64.rpm is not installed                       
(1/6): mysql-community-common-8.0.17-1.el7.x86_64.rpm                         | 589 kB  00:00:00     
(2/6): mysql-community-libs-8.0.17-1.el7.x86_64.rpm                           | 3.0 MB  00:00:01     
(3/6): mysql-community-libs-compat-8.0.17-1.el7.x86_64.rpm                    | 2.1 MB  00:00:00     
Public key for mysql-shell-8.0.17-1.el7.x86_64.rpm is not installed] 5.0 MB/s |  44 MB  00:01:25 ETA 
(4/6): mysql-shell-8.0.17-1.el7.x86_64.rpm                                    |  15 MB  00:00:06     
(5/6): mysql-community-client-8.0.17-1.el7.x86_64.rpm                         |  32 MB  00:00:13     
(6/6): mysql-community-server-8.0.17-1.el7.x86_64.rpm                         | 415 MB  00:01:29     
-----------------------------------------------------------------------------------------------------
Total                                                                5.1 MB/s | 468 MB  00:01:31     
Retrieving key from file:///etc/pki/rpm-gpg/RPM-GPG-KEY-mysql                                        
Importing GPG key 0x5072E1F5:                                                                        
 Userid     : "MySQL Release Engineering <mysql-build@oss.oracle.com>"                               
 Fingerprint: a4a9 4068 76fc bd3c 4567 70c8 8c71 8d3b 5072 e1f5                                      
 Package    : mysql80-community-release-el7-3.noarch (@/mysql80-community-release-el7-3.noarch)      
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-mysql                                                     
Is this ok [y/N]: y                                                                                  
Running transaction check                                                                            
Running transaction test                                                                             
Transaction test succeeded
Running transaction
  Installing : mysql-community-common-8.0.17-1.el7.x86_64                                        1/7
  Installing : mysql-community-libs-8.0.17-1.el7.x86_64                                          2/7
  Installing : mysql-community-client-8.0.17-1.el7.x86_64                                        3/7
  Installing : mysql-community-server-8.0.17-1.el7.x86_64                                        4/7
  Installing : mysql-community-libs-compat-8.0.17-1.el7.x86_64                                   5/7
  Installing : mysql-shell-8.0.17-1.el7.x86_64                                                   6/7
  Erasing    : 1:mariadb-libs-5.5.64-1.el7.x86_64                                                7/7
  Verifying  : mysql-community-libs-8.0.17-1.el7.x86_64                                          1/7
  Verifying  : mysql-community-server-8.0.17-1.el7.x86_64                                        2/7
  Verifying  : mysql-community-common-8.0.17-1.el7.x86_64                                        3/7
  Verifying  : mysql-community-client-8.0.17-1.el7.x86_64                                        4/7
  Verifying  : mysql-shell-8.0.17-1.el7.x86_64                                                   5/7
  Verifying  : mysql-community-libs-compat-8.0.17-1.el7.x86_64                                   6/7
  Verifying  : 1:mariadb-libs-5.5.64-1.el7.x86_64                                                7/7

Installed:
  mysql-community-client.x86_64 0:8.0.17-1.el7        mysql-community-libs.x86_64 0:8.0.17-1.el7
  mysql-community-libs-compat.x86_64 0:8.0.17-1.el7   mysql-community-server.x86_64 0:8.0.17-1.el7
  mysql-shell.x86_64 0:8.0.17-1.el7

Dependency Installed:
  mysql-community-common.x86_64 0:8.0.17-1.el7

Replaced:
  mariadb-libs.x86_64 1:5.5.64-1.el7

Complete!

There are some dependencies that are pulled in and existing libraries are upgraded.

That is it. All that remains is to start MySQL and set the root password. You start MySQL through systemd like:

[opc@mysql ~]$ sudo systemctl start mysqld

Since it is the first time MySQL is started, the data directory (/var/lib/mysql) is initialized and the root account is created with a random password. You can find the random password in the error log:

[opc@mysql ~]$ sudo grep password /var/log/mysqld.log
2019-09-18T09:59:55.552745Z 5 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: i(Y5Nkko>S.t

The password you see will of course be different. Use the password the first time you authenticate, then use the ALTER USER statement to set the new password. For example, using MySQL Shell:

[opc@mysql ~]$ mysqlsh --user=root --sql
Please provide the password for 'root@localhost': ************
Save password for 'root@localhost'? [Y]es/[N]o/Ne[v]er (default No): 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'
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 10 (X protocol)
Server version: 8.0.17 MySQL Community Server - GPL
No default schema selected; type \use <schema> to set one.
 MySQL  localhost:33060+ ssl  SQL > ALTER USER CURRENT_USER() IDENTIFIED BY 'New$secureP@ssw0rd';
Query OK, 0 rows affected (0.0061 sec)

Information

The password validation component is installed by default when installing MySQL using RPMs. This means that the password must be at least eight characters long and include at least one lower case, one upper case, one digit, and one special character.

You are now ready to use MySQL. Have fun.

Hyperconverging and Galera cluster

$
0
0

What is hyperconverging?

Hyperconverging is the latest hype: do things more efficiently with the resources that you have by cramming as many virtual machines on the same hypervisor. In theory this should allow you to mix and match various workloads to make the optimum use of your hypervisor (e.g. all cores used 100% of the time, overbooking your memory up to 200%, moving virtuals around like there is no tomorrow). Any cloud provider is hyperconverging their infrastructure and this has pros and cons. The pro is that it’s much cheaper to run many different workloads while the con clearly is when you encounter noisy neighbors. As Jeremy Cole said: “We are utilizing our virtual machines to the max. If you are on the same hypervisor as us, sorry!”

Apart from cloud providers, you could hyperconverge your infrastructure yourself. There are a few hardware/software vendors out there that will help you with that and at one of my previous employers we got a helping hand from one such vendor!

DIY hyperconverging

In our case the entire infrastructure was migrated to a new hyperconverged infrastructure where we would have multiple infrastructure clusters (read: four hypervisors in one chassis) in multiple data centers. Infra marked one of these DCs suitable for our customer facing projects as the peering was performed in that DC. The idea behind this new infrastructure is that the VM can basically run anywhere in your infrastructure and copied realtime to another hypervisor within the same cluster (read: chassis). This copy process (including memory) obviously required some (short) locking, but it even worked amazingly well. We even had some software running that would move around VMs to optimize the workloads and still retain some spare capacity. Magic!

Now there was an additional benefit to choose for this vendor: if a hypervisor would go down the same VM could be spun up immediately on another hypervisor, albeit without copying the memory contents. To be able to do this, the disks are synced to at least one other hypervisor. This means some cluster magic detects one of the hypervisors being down and automagically spins up the same VMs on another (available) hypervisor that contains the latest data of this VM. To spread the load among various hypervisors the replication factor of the disks is advised to be set to 2, where 2 means to be copied to (at least) two other hypervisors.

Hyperconverging Galera

Our Galera cluster consisted out of three Galera nodes and three asynchronous read replicas attached (see image below).

Galera cluster with read slaves

Galera cluster with read slaves

In this picture every Galera node stores every transaction in the GCache, InnoDB flushes the transaction to disk (ibdata*) and asynchronous replication dictates another write to the binlogs. That means that every transaction in our Galera node will already be stored three times on disk.

The hyperconverged cluster where we hosted Galera had the replication factor set to 2. That means every byte written to disk will be written to at least two other storage controllers (VMs), as shown in the image below. This write operation over the network is synchronously, so the filesystem has to wait until both controllers acknowledged the write. Latency of this write is negligible as the write is super fast and performed over a low latency network. The magic behind this synchronous disk replication is out of the scope for this blog post, but I can hint that a certain NoSQL database (named after some Greek mythology) is managing the storage layer.

Hyperconverge write amplification: every write to disk will be written three times!

Hyperconverge write amplification: every write to disk will be written three times!

This means that every write to disk in our Galera node will also be synced an additional two hypervisors. To make matters worse, due to semi-synchronous replication, all three nodes Galera perform the exact same operations at (almost) the exact same time!

1 transaction = 3 nodes (3 writes locally + 6 writes over the network) = 27 writes

As you can guess from the simple formula above: 9 writes are performed locally and 18 writes are performed over the network. As every write to disk is performed synchronously over the network, this write adds a bit more than negligible latency when it spawns 18 writes over the network at the same time. As 1 transaction to Galera can cause 18 synchronous writes over the network, imagine what latency you will encounter if you have a baseline of 200 transactions per second! And we’re not even counting the asynchronous replicas performing similar write operation again mere (milli)seconds later!

Galera managed to cope, but instability only happened on set intervals. We could trace these back to our so called stock-updates or pricing-updates: every half-an-hour stock levels were pushed from the warehouse database and every few hours new pricing information was also pushed via the enterprise service bus.

With more than a million products in the database these torrents of writes quickly caused disk latency in the entire hyperconverged cluster and we have seen the disk latency shoot up well beyond 80ms. This no longer affected the Galera cluster, but this was causing cluster wide issues on the distributed storage layer as well. And to make matters even worse: latency on the entire network was also shooting up.

Benchmarking semi-synchronously replicated hyperconverged clusters

At first nobody believed us, even when we showed the graphs to the vendor. This new infrastructure was so much more expensive than our old that it simply couldn’t be true. Only after conducting benchmarks, reproducing the latency on an empty test cluster, we were taken seriously. The benchmarks revealed that the write amplification saturated the network interfaces of the cluster and we worked with the vendor on seeking a solution to the problem. Even after upgrading the network (10G interface bonding, enabling jumbo frames, hypervisor tuning) we still found latency issues.

The issue with our hyperconverged cluster was that there was no (separate) internal network handling the inter-hypervisor network traffic. Of course we could now achieve the double amount of transactions, but that didn’t solve the underlying issue of also causing latency on other VMs and also causing latency on ingress and egress network of our applications.

Conclusion

We came to the conclusion that (semi-)synchronous replicated databases and hyperconverged infrastructures with high replication factors don’t match. Unfortunately this replication factor could only be set on cluster level and not on an individual VM level. Also the reasoning behind the synchronous disk replication did not make sense (see also my previous blog post) as Galera would wipe the disk contents anyway and in general it would take quite some time for the database to recover, so a quick failover would not happen anyway. That’s why we ran Galera+ProxySQL in the first place: to allow us to have a failover happen within seconds!

We also ran other (semi-)synchronous replicated databases: MongoDB, SOLR and Elasticsearch for example and each an everyone of them basically the same lack of need for disk replication.

The only option left was to migrate the Galera cluster back to our old hardware that, luckily/sadly, was still switched on. At the same time we started working on a migration to a real cloud vendor as they could offer us better performance without the risk of a single point of failure (e.g. single data center).

So what difference would a benchmark up front have made?

This only happened due to bad requirements without analyzing the workload that was supposed to be converged. We would have seen these issues before migrating to the new hyperconverged infrastructure if we would have benchmarked beforehand. We would have saved us from many instabilities, outages and post mortems. We might even have chosen a totally different setup or have chosen to split our workloads over multiple (smaller) hyperconverged clusters.

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.

Protecting Your MySQL Servers From Ransomware

$
0
0

Author: Robert Agar

A constant in the computing world is that it is always evolving and offering new challenges and opportunities. Software solutions come and go with some becoming staples in the business community while others barely cause a ripple as they disappear into the ether. Take MySQL as an example. From its humble beginnings in 1994, the platform has grown to become the most popular SQL database in 2019. If you are a database professional, chances are very good that you work with MySQL regularly.

The popularity of the database platform has not gone unnoticed by the unscrupulous entities that engage in cybersecurity attacks with nefarious intentions. Whether acting as individuals or combining forces into rogue teams, cybercriminals are always looking for new and ingenious ways to cause havoc with your IT environment. Their intrusions can take many forms, from implanting malware in an attempt to steal login credentials to randomly deleting data on your systems.

A particularly nasty type of cyberattack is carried out by ransomware. This is a specific form of malware whose goal is to encrypt the data on an infected computer. This makes the data inaccessible to users and can cripple an organization. The criminals behind the attack claim they will unencrypt the data if their financial demands are met. Paying the ransom may or may not get your data back. Remember, you are dealing with criminals and their word is not to be trusted.

Targeted MySQL Ransomware Attacks

In recent years, MySQL databases have become a target for cybercriminals wielding ransomware. The large installed base of the software provides many potential victims of financial blackmail. Even if only a fraction of the attacks are successful, the criminals stand to take down a lot of systems and possibly make some serious money.

Recently, MySQL servers began being hit with attacks trying to implant a ransomware weapon known as GandCrab. The perpetrators behind the ransomware have been targeting specific environments in attempts to thwart defensive actions. As of March 2018, over 50,000 machines have been infected with the majority of targets being systems located in the US and UK.

Security experts at Sophos have researched the GandCrab malware and have made some interesting discoveries. For one, though the IP address of the server hosting the sample of the code under study is in Arizona, the user interface of the HFS installation is in simplified Chinese. This suggests that there may be an international cybercriminal team behind these attacks who have compromised a US server.

The security firm used a honeypot designed to lure hackers so their tools can be studied and appropriate defenses developed. They were listening on the default TCP port for MySQL servers which is 3306. The attack was executed in stages with the first step verifying that the database server in question was running MySQL.

Once that was determined, the set command was used to upload the bytes to construct a helper DLL. The DLL was used to add three malicious functions to the database. These functions were employed to download the GandCrab payload from a remote machine and place it in the root of the C: drive with the name isetup.exe and then executed the program.

At this point, your system has been infected and your files will be encrypted. Hopefully, you have a robust backup and recovery policy and can recover your system without resorting to acceding to the ransom demands.

Hackers are searching for MySQL logins that are not properly protected. This may be due to a weak password or in some egregious cases, no password at all. Failure to protect your MySQL database may allow hackers to turn it into a launching pad for malware. Some suggestions for protecting your MySQL servers from ransomware are to:

  • Insist on strong passwords.
  • Eliminate the ability to directly access your MSQL servers from the Internet.
  • Monitor your MySQL control settings.

Keeping Tabs on Your Systems is a Crucial Defensive Tactic

Possessing insight into the operation of your MySQL servers provides a baseline from which you can discover discrepancies and unusual behavior. Monitoring supplies the perfect vehicle for this practice and can be useful in many areas of database administration. It can identify effective optimization initiatives and help you to increase user satisfaction with your systems. It can also be instrumental in alerting you to any suspicious activity which may indicate you are being attacked.

SQL Diagnostic Manager for MySQL provides a comprehensive monitoring application that can address all aspects of your MySQL environment. It includes over 600 pre-built monitors that return information on security, excessive privileges, and connection history among many other important details pertaining to your MySQL instance. Set alerts which trigger when thresholds are met that warrant your attention and may help you keep your systems safe from cybercriminals.

Rest assured that GandCrab is not the last attempt to exploit vulnerabilities that are bound to be discovered in MySQL. Start monitoring your systems today to track changes in activity and access that might keep the bad guys at bay.

The post Protecting Your MySQL Servers From Ransomware appeared first on Monyog Blog.


What’s Faster? COUNT(*) or COUNT(1)?

$
0
0

One of the biggest and undead myths in SQL is that COUNT(*) is faster than COUNT(1). Or was it that COUNT(1) is faster than COUNT(*)? Impossible to remember, because there’s really no reason at all why one should be faster than the other. But is the myth justified?

Let’s measure!

How does COUNT(…) work?

But first, let’s look into some theory. The two ways to count things are not exactly the same thing. Why?

  • COUNT(*) counts all the tuples in a group
  • COUNT(<expr>) counts all the tuples in a group for which <expr> evaluates to something that IS NOT NULL

This distinction can be quite useful. Most of the time, we’ll simply COUNT(*) for convenience, but there are (at least) two cases where we don’t want that, for example:

When outer joining

Imagine that in the Sakila database, we have some actors that did not play in any films. Making sure such an actor actually exists:

INSERT INTO actor (actor_id, first_name, last_name)
VALUES (201, 'SUSAN', 'DAVIS');

When inner joining, we might write the following (using PostgreSQL syntax):

SELECT actor_id, a.first_name, a.last_name, count(*) AS c
FROM actor AS a
JOIN film_actor AS fa USING (actor_id)
JOIN film AS f USING (film_id)
GROUP BY actor_id
ORDER BY c ASC, actor_id ASC;

And we won’t get the newly added SUSAN DAVIS, because of the nature of inner join:

actor_id|first_name |last_name   |c |
--------|-----------|------------|--|
     148|EMILY      |DEE         |14|
      35|JUDY       |DEAN        |15|
     199|JULIA      |FAWCETT     |15|
     186|JULIA      |ZELLWEGER   |16|
      31|SISSY      |SOBIESKI    |18|
      71|ADAM       |GRANT       |18|
       1|PENELOPE   |GUINESS     |19|
      30|SANDRA     |PECK        |19|

So we might change our query to use LEFT JOIN instead

SELECT actor_id, a.first_name, a.last_name, count(*) AS c
FROM actor AS a
LEFT JOIN film_actor AS fa USING (actor_id)
LEFT JOIN film AS f USING (film_id)
GROUP BY actor_id
ORDER BY c ASC, actor_id ASC;

There she is now, but oops, wrong count! She doesn’t have any films, which we have proven before with the INNER JOIN query. Yet we get 1:

actor_id|first_name |last_name   |c |
--------|-----------|------------|--|
     201|SUSAN      |DAVIS       | 1|
     148|EMILY      |DEE         |14|
      35|JUDY       |DEAN        |15|
     199|JULIA      |FAWCETT     |15|
     186|JULIA      |ZELLWEGER   |16|
      31|SISSY      |SOBIESKI    |18|
      71|ADAM       |GRANT       |18|
       1|PENELOPE   |GUINESS     |19|
      30|SANDRA     |PECK        |19|

Her COUNT(*) value is 1, because we do get 1 film tuple for her in the group, with all columns being NULL. The solution is to count the FILM_ID instead, which cannot be NULL in the table (being a primary key), but only because of the LEFT JOIN:

SELECT actor_id, a.first_name, a.last_name, count(film_id) AS c
FROM actor AS a
LEFT JOIN film_actor AS fa USING (actor_id)
LEFT JOIN film AS f USING (film_id)
GROUP BY actor_id
ORDER BY c ASC, actor_id ASC;

Notice, we could count other things than the primary key, but with the primary key, we’re quite certain we don’t get any other “accidental” nulls in our groups, which we did not want to exclude from the count value.

Now, we’re getting the correct result:

actor_id|first_name |last_name   |c |
--------|-----------|------------|--|
     201|SUSAN      |DAVIS       | 0|
     148|EMILY      |DEE         |14|
      35|JUDY       |DEAN        |15|
     199|JULIA      |FAWCETT     |15|
     186|JULIA      |ZELLWEGER   |16|
      31|SISSY      |SOBIESKI    |18|
      71|ADAM       |GRANT       |18|
       1|PENELOPE   |GUINESS     |19|
      30|SANDRA     |PECK        |19|

When counting subsets of a group

An even more powerful application of counting only non-null evaluations of an expression is counting only subsets of a group. We’ve already blogged about this technique in our previous post about aggregating several expressions in one single query.

For example, counting in a single query:

  • All actors
  • Actors with their first_name starting with A
  • Actors with their first_name ending with A
  • Actors with their first_name containing A

In SQL:

SELECT 
  count(*),
  count(CASE WHEN first_name LIKE 'A%' THEN 1 END),
  count(CASE WHEN first_name LIKE '%A' THEN 1 END),
  count(CASE WHEN first_name LIKE '%A%' THEN 1 END)
FROM actor;

This yields:

count|count|count|count|
-----|-----|-----|-----|
  201|   13|   30|  105|

This is very useful when pivoting data sets (see also Oracle/SQL Server PIVOT clause).

Notice that PostgreSQL supports the SQL standard FILTER clause for this, which is more convenient and more readable. The above query can be written like this, in PostgreSQL:

SELECT 
  count(*),
  count(*) FILTER (WHERE first_name LIKE 'A%'),
  count(*) FILTER (WHERE first_name LIKE '%A'),
  count(*) FILTER (WHERE first_name LIKE '%A%')
FROM actor;

Back to COUNT(*) vs COUNT(1)

Now that we now the theory behind these COUNT expressions, what’s the difference between COUNT(*) and COUNT(1). There is none, effectively. COUNT(1) evaluates a constant expression for each row in the group, and it can be proven that this constant expression will never evaluate to NULL, so effectively, we’re running COUNT(*), counting ALL the rows in the group again.

There should be no difference, and parsers / optimisers should be able to recognise this and not do the extra work of checking every expression evaluation for NULL-ness.

I recently saw this discussion on Twitter, though, where Vik Fearing looked up the PostgreSQL sources, showing that PostgreSQL does do the extra work instead of optimising this:

So, I was curious to see if it mattered. I ran a benchmark on the 4 most popular RDBMS, with these results:

  • MySQL: Doesn’t matter. Sometimes COUNT(1) was faster, sometimes COUNT(*) was faster, so all differences were only benchmark artifacts
  • Oracle: Doesn’t matter. Like MySQL
  • PostgreSQL: Does matter (!). COUNT(*) was consistently faster by around 10% on 1M rows, that’s much more than I had expected
  • SQL Server: Doesn’t matter. Like MySQL

The benchmark code can be found in the following gists:

The results are below. Each benchmark run repeated SELECT COUNT(*) FROM t or SELECT COUNT(1) FROM t 100 times on a 1M row table, and then the benchmark was repeated 5 times to mitigate any warmup penalties and be fair with respect to caching.

The times displayed are relative to the fastest run. This removes any distraction that may be caused by interpreting actual execution times as we do not want to compare database products against each other.

The database versions I’ve used are:

  • MySQL 8.0.16 (in Docker)
  • Oracle 18c XE (in Docker)
  • PostgreSQL 11.3 (in Docker)
  • SQL Server 2017 Express (in Windows)

MySQL

No relevant difference, nor a clear winner:

RUN     STMT    RELATIVE_TIME
-----------------------------
0	1	1.0079
0	2	1.0212
1	1	1.0229
1	2	1.0256
2	1	1.0009
2	2	1.0031
3	1	1.0291
3	2	1.0256
4	1	1.0618
4	2	1.0000

Oracle

No relevant difference, nor a clear winner

Run 1, Statement 1 : 1.06874
Run 1, Statement 2 : 1.01982
Run 2, Statement 1 : 1.09175
Run 2, Statement 2 : 1.0301
Run 3, Statement 1 : 1.00308
Run 3, Statement 2 : 1.02499
Run 4, Statement 1 : 1.02503
Run 4, Statement 2 : 1
Run 5, Statement 1 : 1.01259
Run 5, Statement 2 : 1.05828

PostgreSQL

A significant, consistent difference of almost 10%:

RUN 1, Statement 1: 1.00134
RUN 1, Statement 2: 1.09538
RUN 2, Statement 1: 1.00190
RUN 2, Statement 2: 1.09115
RUN 3, Statement 1: 1.00000
RUN 3, Statement 2: 1.09858
RUN 4, Statement 1: 1.00266
RUN 4, Statement 2: 1.09260
RUN 5, Statement 1: 1.00454
RUN 5, Statement 2: 1.09694

Again, I’m surprised by the order of magnitude of this difference. I would have expected it to be less. Curious to hear about your own results in the comments, or further ideas why this is so significant in PostgreSQL.

SQL Server

No relevant difference, nor a clear winner

Run 1, Statement 1: 1.00442
Run 1, Statement 2: 1.00702
Run 2, Statement 1: 1.00468
Run 2, Statement 2: 1.00000
Run 3, Statement 1: 1.00208
Run 3, Statement 2: 1.00624
Run 4, Statement 1: 1.00780
Run 4, Statement 2: 1.00364
Run 5, Statement 1: 1.00468
Run 5, Statement 2: 1.00702

Conclusion

As it is now in 2019, given the database versions mentioned above, unfortunately, there is a significant difference between COUNT(*) and COUNT(1) in PostgreSQL. Luckily (and this is rare in SQL), all the other dialects don’t care and thus, consistently using COUNT(*), rather than COUNT(1) is a slightly better choice for ALL measured database products from this article.

Do note that the benchmark only tried a very simple query! The results might be different when using joins, unions, or any other SQL constructs, or in other edge cases, e.g. when using COUNT() in HAVING or ORDER BY or with window functions, etc.

In any case, there shouldn’t be any difference, and I’m sure that a future PostgreSQL version will optimise the constant expression in the COUNT(<expr>) aggregate function directly in the parser to avoid the extra work.

For other interesting optimisations that do not depend on the cost model, see this article here.

My MySQL Account Has TWO Passwords

$
0
0
Dear Dave,

My DBA told me that an account I use to talk to my MySQL database instance has TWO passwords! How does that happen? Do I have to provide both passwords every time? 

Sincerely,

A Confused User Who Does Not Want to Type Two Passwords All The Time


Dear Confused User,

Dual Password Support was added in MySQL 8.0.14 and it is a very handy thing. User accounts can now have a primary password and a secondary password. Image a scenario where you are rotating passwords as directed by your company policy but it takes a while to change the credentials in all your code despite your best EMACS magic. The ability to keep the servers up and active as your do your security due diligence is very helpful.

And you do not need to type both password! Just one and hopefully the newer one.

How Do You Establish A Secondary Password?


Very simple.

ALTER USER 'dave'@'deardave.xyz' IDENTIFIED BY 'deardave2' RETAIN CURRENT PASSWORD;

In the mysql.user table there is now a JSON column named User_attributes that now has the secondary password:

 {"additional_password": "$A$005$;H7\u001b\u001b\u0006<`qFRU\tNRxT Z\u0003Ya/iej8Az8LoXGTv.dtf9K3RdJuaLFtXZHBs3/DntG2"} 


And How Do I Get Rid Of A Secondary Password


So you are done with updating the password and want to remove the old password? Simply use another ALTER TABLE.

ALTER USER 'dave'@'deardave'xyz' DISCARD OLD PASSWORD

Things To Note


RETAIN CURRENT PASSWORD keeps the old password in the additional_password key/value pair. The new password becomes the primary. And if the new password is empty both the primary and secondary passwords will be empty.

If you try to add a secondary password to an account without a password it will fail.

If the account has a secondary password by you change the primary password


One, two, three, MySQLers… OOW 2019, Percona Live, ProxySQL Tech Day!

$
0
0

As people are getting back from vacations and application traffic is going back and hitting database backend hard, it is a good time to think about performance and prepare for the winter holiday spike. Whenever you are on-premise or in the cloud, questions are the same:

  • Are we satisfied with the current MySQL performance?
  • How much traffic are we currently serving?
  • Is there enough capacity to stay stable as traffic increases?
  • What would be the best way to stay cost-effective as we grow?

Unfortunately, the answers are not so obvious and require a thorough performance analysis. However, there is a chance that your problem has already been solved by someone else. I do not mean StackOverflow (which is a beautiful place, by the way), but some higher level questions which people usually discuss at conferences, and we have several of them ongoing or just a couple of weeks away.

Right this moment René Cannào and Peter Boros are preparing to deliver their talk MySQL with ProxySQL at Zuora at Oracle Open World conference, 09:00 AM @ Room 301, Moscone South.

At the same time next door in the Room 312 Oracle’ Frederic Descamps will be talking about MySQL Shell for DBAs.

If you are a developer, than you probably won’t miss Seventeen Things Developers Need to Know About MySQL by Peter Zaitsev 11:15 AM @ Room 3.

But that’s California, and what if you’re in Europe? Please hold on, we’re crossing the Atlantic!

Let’s move to Amsterdam where you might want to attend Percona Live Europe held from September 30th to October 2nd. As you land, you will not even need a taxi to get there as your venue is next to the airport! Besides useful tutorials on the first day, there will be two complete days filled with Database Wisdom. Perconians and their guests will share virtually every aspect of the database performance and operations.

Here is a list of my favorite talks from day one @ Percona Live:

  • MyRocks and RocksDB Advanced Features and Performance by Yoshinori Matsunobu (2:30 PM),
  • ClickHouse Features to Blow Your Mind by  Aleksei Milovidov (6:00 PM),
  • Tracing and Profiling MySQL by Valerii Kravchuk (same 6:00 PM).

The next day is also full of great talks, here’re just some examples:

  • Sveta Smirnova helps you to save life with Histograms (9:00 AM),
  • Marco Tusa will make a deep dive into Using ProxySQL as Firewall (10:00 AM),
  • Morgan Tocker will share his First 90 days experience with Vitess (11:00 AM).
  • And if you are looking for real hardcore stuff, please visit gdb basics for MySQL DBAs  by Valerii Kravchuk (3:30 PM).

That’s a really intense line-up for three days, but that’s not the end! Here comes the ProxySQL Tech Day…

Right after Percona Live, on Thursday Oct 3rd, we are going to meet in person at a free event in Ghent, Belgium. We’ll be talking specifically about large-scale MySQL environments and how to serve a really huge amount of transactions with MySQL. Experts from 5 different companies will gather at Co.Station Gent and share their knowledge. Tricky questions, mind-breaking cases, crazy requirements and challenges of all kinds are super welcome! Please use this form and be sure that we’ll tackle your issue.

We’re starting at 5:00 PM, so you will have some time for a walk across the nice City of Ghent!

P.S. The views expressed here are my own and do not necessarily reflect the opinion of my employer.

How To Bulk Import Data Into InnoDB Cluster?

$
0
0
If you need to do bulk importing into InnoDB Cluster, it is certainly possible to do so by using any of:


Unfortunately both imports will add load to instances and to channels interconnecting instances: data imported on the primary instance needs to be replicated to the rest of instances. And the bigger the data to import, the higher the load (and this could end up affecting). The import operation could be batched to reduce load, and Group Replication allows at least to throttle workload with flow control or to split messages in several smaller messages with group_replication_communication_max_message_size option.

How to import data into InnoDB Cluster?
But in case data is a whole table (MySQL 8 adds also flexibility to swap partitions and tables, may become handy), or data can be first loaded into an InnoDB table, there's simple way to have an arbitrary amount of data pushed to InnoDB Cluster, and it takes advantage of tablespaces copying feature. I made a quick test to import a table.

I created the table t5 on an arbitrary instance and added a few rows. Then exported as in the instructions (does nothing but flush it and create an auxiliary .cnf file for definition validation at import time, not mandatory to use it but recommended):

FLUSH TABLES t5 FOR EXPORT;

On the InnoDB Cluster setup, I created the table t5 with same definition from the primary, then again on the primary:

ALTER TABLE t5 DISCARD TABLESPACE;

This will remove the t5.ibd tablespace on all the 3 instances. And with a simple SELECT, I made sure that this is as expected:

mysql> select * from test.t5;
ERROR 1814 (HY000): Tablespace has been discarded for table 't5'

After that, I copied t5.ibd from the former instance under the related schema folder in *each* GR node.
Let's check initial GTID set:

mysql> select @@GLOBAL.GTID_EXECUTED;
+------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                                     |
+------------------------------------------------------------+
| 550fa9ee-a1f8-4b6d-9bfe-c03c12cd1c72:1-270:1000011-1000014 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

Then on the primary, did:

mysql> ALTER TABLE t5 IMPORT TABLESPACE;
Query OK, 0 rows affected, 1 warning (0.03 sec)

I am lazy and did not perform validation using .cfg (more from the instructions):

mysql> show warnings;
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Level   | Code | Message                                                                                                                                 |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1810 | InnoDB: IO Read error: (2, No such file or directory) Error opening './test/t5.cfg', will attempt to import without schema verification |
+---------+------+-----------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

And all the tablespaces are loaded from local file system into the GR member. And new GTID set is:

mysql> select @@GLOBAL.GTID_EXECUTED;
+------------------------------------------------------------+
| @@GLOBAL.GTID_EXECUTED                                     |
+------------------------------------------------------------+
| 550fa9ee-a1f8-4b6d-9bfe-c03c12cd1c72:1-271:1000011-1000014 |
+------------------------------------------------------------+
1 row in set (0.00 sec)

Let's test it's all ok:

mysql> select * from test.t5;
+------+
| a    |
+------+
|    1 |
|    2 |
|    3 |
|    4 |
|    5 |
|    6 |
|    7 |
|  777 |
+------+
8 rows in set (0.00 sec)

So data will be available on the rest of the nodes at no bandwidth and protocol cost, only this is indeed replicated, from binlog.

# at 2714
#190919  1:34:34 server id 1  end_log_pos 2821  Query   thread_id=34    exec_time=0     error_code=0
SET TIMESTAMP=1568849674/*!*/;
ALTER TABLE t5 IMPORT TABLESPACE
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;

Most important, I broke nothing!

mysql> SELECT MEMBER_ID, MEMBER_STATE FROM performance_schema.replication_group_members;
+--------------------------------------+--------------+
| MEMBER_ID | MEMBER_STATE |
+--------------------------------------+--------------+
| 43a67ea3-e1a0-11e7-8a9a-0021f66e910e | ONLINE |
| 45ab082d-e1a0-11e7-8b73-0021f66e910e | ONLINE |
| 48be28c0-e1a0-11e7-8c19-0021f66e910e | ONLINE |
+--------------------------------------+--------------+
3 rows in set (0.00 sec)


To wrap up, instead of loading GB or TB into InnoDB Cluster and have the cluster replicate it, this trick can push your data at no cost.
Comments are welcome!

Percona Kubernetes Operator for Percona XtraDB Cluster 1.2.0 Now Available

$
0
0
Kubernetes Operator for XtraDB Cluster

Percona Kubernetes Operator for Percona XtraDB Cluster 1.2.0We are glad to announce the 1.2.0 release of the  Percona Kubernetes Operator for Percona XtraDB Cluster.

The Percona Kubernetes Operator for Percona XtraDB Cluster automates the lifecycle and provides a consistent Percona XtraDB Cluster instance. The Operator can be used to create a Percona XtraDB Cluster, or scale an existing Cluster, and contains the necessary Kubernetes settings.

The Operator simplifies the deployment and management of the Percona XtraDB Cluster in Kubernetes-based environments. It extends the Kubernetes API with a new custom resource for deploying, configuring and managing the application through the whole life cycle.

The Operator source code is available in our Github repository. All of Percona’s software is open-source and free.

New features and improvements

  • A Service Broker was implemented for the Operator, allowing a user to deploy Percona XtraDB Cluster on the OpenShift Platform, configuring it with a standard GUI, following the Open Service Broker API.
  • Now the Operator supports Percona Monitoring and Management 2, which means being able to detect and register to PMM Server of both 1.x and 2.0 versions.
  • A NodeSelector constraint is now supported for the backups, which allows using backup storage accessible to a limited set of nodes only (contributed by Chen Min).
  • The resource constraint values were refined for all containers to eliminate the possibility of an out of memory error.
  • Now it is possible to set the schedulerName option in the operator parameters. This allows using storage which depends on a custom scheduler, or a cloud provider which optimizes scheduling to run workloads in a cost-effective way (contributed by Smaine Kahlouch).
  • A bug was fixed, which made cluster status oscillate between “initializing” and “ready” after an update.
  • A 90 second startup delay which took place on freshly deployed Percona XtraDB Cluster was eliminated.

Percona XtraDB Cluster is an open-source, cost-effective and robust clustering solution for businesses. It integrates Percona Server for MySQL with the Galera replication library to produce a highly-available and scalable MySQL® cluster complete with synchronous multi-master replication, zero data loss and automatic node provisioning using Percona XtraBackup.

Help us improve our software quality by reporting any bugs you encounter using our bug tracking system.

Are your Database Backups Good Enough?

$
0
0

In the last few years there have been several examples of major service problems affecting businesses data: outages causing data inconsistencies; unavailability or data loss, and worldwide cyberattacks encrypting your files and asking for a ransom.

Database-related incidents are a very common industry issue- even if the root cause is not the database system itself. No matter if your main relational system is MySQL, MariaDB, PostgresQL or AWS Aurora -there will be a time where you will need to make use of backups to recover to a previous state. And when that happens it will be the worst time to realize that your backup system hadn’t been working for months, or testing for the first time a cluster-wide recovery.

Forget about the backups, it is all about recovery!

Let me be 100% clear: the question is not IF data incidents like those can happen to you, but WHEN it will happen and HOW you are prepared to respond to them. It could be a bad application deploy, an external breach, a disgruntled employee, a hardware failure, a provider problem, ransomware infection or a network failure,… Your relational data will eventually get lost, corrupted or in an inconsistent state, and “I have backups” will not be good enough. Recovery plans and tools have to be in place and in a healthy state.

As the only 2 Site Reliability Engineers in charge of the Database Layer of Wikipedia and other projects at the Wikimedia Foundation, Manuel and I grew worried on how to improve both our existing data recovery strategy and provisioning systems. We have the responsibility to make sure that free knowledge contributed by millions of volunteers around the world keeps being available for future generations. As a colleague of us once said- no worries, we “only” are in charge of maintaining the (probably) most valuable collaborative database ever created in the history of mankind! 😀

Among the two of us we handle over half a petabyte of relational data over hundreds of instances and servers, and manual work is off-limits to be efficient. Unlike other popular Internet services, we not only store metadata in MariaDB databases, we also store all content (Wikitext).

  • We needed a system that was incredibly flexible– so it worked for both large Wiki databases (like the many terabytes of the English Wikipedia), but also for small but important internal database services such as our bug tracker-.
  • fast -able to recover data saturating our 10Gbit network-,
  • granular– being able to recover 1 row or an entire instance, to 1 server or an entire cluster; at any arbitrary point in the past-
  • and reliable -low rate of failure, but when it failed it should be detected immediately, and not when it is too late.
  • The system had to use exclusively free (open source) software and be published itself with a free license.

We ended up with something like this (simplified view :-P):

Workflow of backups and recovery at the Wikimedia Foundation

Like any application, a recovery system is never complete. However after a year of planning, developing and deploying our solution, we are ready to share what we have finished so far to people outside of our organization.

Our Presentation at Percona Live Europe 2019

A single blog post is not enough to tell the whole story of how we reached the current state – that is why we are going to present the work at the Percona Live Europe 2019 conference which will take place 29 September–2 October in Amsterdam. We will introduce what was the problem we wanted to solve, our design philosophy, existing tooling used and backup methods, backups checking, recovery verification and general automation. You will be able to compare with your own setup and ask questions about why we chose certain paths, based on our experience.

What we have setup may not be perfect, and may not work for you- your needs will be different, as well as your environment. However I expect our presentation will inspire you to design and setup better recovery systems in the future.

See you in Amsterdam! And if you haven’t yet registered, then you are invited to use the code CMESPEAK-JAIME 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 Are your Database Backups Good Enough? appeared first on Percona Community Blog.

MySQL Server Performance Tuning: The Perfect Scalability

$
0
0
When data and concurrency grow, tgether with queries complexity, a standard configuration does not fit anymore. This content walks through the ways MySQL has to adapt to an ever-increasing amount of data in context of tuning, under the heading “multiplication”:
—Scaling up through partitioning and how partitioning can help manage/archive data
—How to relocate binlog, undo, redo, tablespaces, on disk temporary tables and more on different mount points to take advantage of multiple storages and tackle I/O bottlenecks
—All improvements to parallel slave replication
—A quick OS approach, to verify swapping and affinity tuning take the most out of the machine.

All of this with different approaches to monitor the instance to spot what parts of the system and what queries need to be considered, mainly using:

Sys Schema
Global Status
SHOW ENGINE INNODB STATUS



I presented this content at last Oracle Open World 2019 as a Hands-On Lab.

MySQL 8 Password Validation with validate_password component

$
0
0

Properly planned MySQL Password Management is the first step to protect your database


We at MinervaDB provide MySQL and  MariaDB Database Security Audit (Please read about our Security Practice at MinervaDB Consulting Page) for our customers globally, We don’t go easy with password management .. Weaker passwords are serious security threats and we highly recommend stronger passwords. Technically Password Validation is about the policies that every new password must comply and this task is taken care by validate_password component in MySQL, You have several system variables to configure validate_password component and status variables to monitor

To use validate_password component you must install it first:

Verify if validate_password component is installed:

mysql> select * from mysql.component;

Empty set (0.00 sec)

We have successfully verified validate_password component is not installed 👆

Install validate_password component next and confirm:

mysql> INSTALL COMPONENT 'file://component_validate_password';

Query OK, 0 rows affected (0.01 sec)

mysql> select * from mysql.component;

+--------------+--------------------+------------------------------------+

| component_id | component_group_id | component_urn                      |

+--------------+--------------------+------------------------------------+

|            4 |                  4 | file://component_validate_password |

+--------------+--------------------+------------------------------------+

1 row in set (0.00 sec)

Validate_component system variables :

mysql> SHOW VARIABLES LIKE 'validate_password.%';

+--------------------------------------+--------+

| Variable_name                        | Value  |

+--------------------------------------+--------+

| validate_password.check_user_name    | ON     |

| validate_password.dictionary_file    |        |

| validate_password.length             | 8      |

| validate_password.mixed_case_count   | 1      |

| validate_password.number_count       | 1      |

| validate_password.policy             | MEDIUM |

| validate_password.special_char_count | 1      |

+--------------------------------------+--------+

7 rows in set (0.06 sec)

Validate_component system variables are explained very well in MySQL documentation here – https://dev.mysql.com/doc/refman/8.0/en/validate-password-options-variables.html

Password Validation Component Status Variables

Once validate_password component is enabled, We will have access to MySQL status variables that provide operational information:

mysql> SHOW STATUS LIKE 'validate_password.%';

+-----------------------------------------------+---------------------+

| Variable_name                                 | Value               |

+-----------------------------------------------+---------------------+

| validate_password.dictionary_file_last_parsed | 2019-09-21 01:45:41 |

| validate_password.dictionary_file_words_count | 0                   |

+-----------------------------------------------+---------------------+

2 rows in set (0.02 sec)

Validate_component in action

Simple and easy passwords are not accepted any loner, Let’s test that now:

mysql> create user 'shiv'@'localhost' identified by 'minervadb'; 

ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

Works when we set much better password:

mysql> create user 'shiv'@'localhost' identified by 'Ind@19#47';

Query OK, 0 rows affected (0.02 sec)

mysql>

We will make it even better with password expiry management, i.e. user (shiv) should be changing password every 30 days:

mysql> alter user 'shiv'@'localhost' PASSWORD EXPIRE INTERVAL 30 DAY;

Query OK, 0 rows affected (0.01 sec)

Let’s confirm the password expiry of 30 days configured  for user “shiv”:

mysql> select password_last_changed, password_lifetime from mysql.user where user='shiv';

+-----------------------+-------------------+

| password_last_changed | password_lifetime |

+-----------------------+-------------------+

| 2019-09-21 15:46:11   |                30 |

+-----------------------+-------------------+

1 row in set (0.01 sec)

Dual Active passwords (Thank you Booking.com for this feature request)

We can configure MySQL 8.0 (since8.0.14) with Primary and Secondary Passwords (dual password mechanism), This feature is really helpful in production when changing the password, We have explained it below:

mysql> select version();

+-----------+

| version() |

+-----------+

| 8.0.17    |

+-----------+

1 row in set (0.01 sec)

mysql> alter user 'shiv'@'localhost' identified by 'India#19@47' retain current password;

Query OK, 0 rows affected (0.02 sec)

mysql>

You can discard old password of the user “shiv” when appropriate, Let’s do that next:

mysql> ALTER USER 'shiv'@'localhost' DISCARD OLD PASSWORD;

Query OK, 0 rows affected (0.00 sec)

Conclusion

MySQL 8.0 password management is very interesting, Much better and secured database infrastructure operations is made possible without much complications, We have already customers on this feature, At WebScale the database security is very important to protect the best interests of every stakeholder., Hope you enjoyed reading this blog, Thank you !

The post MySQL 8 Password Validation with validate_password component appeared first on MySQL Consulting, Support and Remote DBA Services.

SQL Char Function Example | Char Function In SQL Tutorial

$
0
0
SQL Char Function Example | Char Function In SQL Tutorial

SQL Char Function Example | Char Function In SQL Tutorial is today’s topic. SQL CHAR function is used for converting a numeric value to a character. It is just the opposite of the ASCII function. A character or string function is a function which takes one or more characters or numbers as parameters and returns the character value.

SQL Char Function

The CHAR() function returns a character based on the ASCII code.

See the following syntax.

Select CHAR (number_code)

Number_code

The number from which character is to be retrieved. An integer outside the range 0 to 255 will return a NULL character.

See the following code.

SELECT CHAR (97);

See the output.

a

Explanation

As ASCII value of a is 97 so character a is printed when number 97 was given as an input to the function.

Let’s see the second query.

SELECT CHAR (65);

See the output.

A

Explanation

As ASCII value of A is 65, so character A is printed when number 65 was given as an input to the function.

Range of ASCII values for characters

A-Z: 65-90
a-z: 97-122

Let’s apply the ASCII function to a table.

Table: Employee

Emp_id Emp_name City State Salary
101 Rohit Raj Patna Bihar 30000
102 Shiva Rana Jalandhar Punjab 20000
103 Karan Kumar Allahabad Uttar Pradesh 40000
104 Suraj Bhakat Kolkata West Bengal 60000
105 Akash Cherukuri Vizag Andhra Pradesh 70000

 

Suppose we want to print the Character Code for Emp_id of Emp_Name, then the following query has to be considered.

See the following query.

Select Emp_name, CHAR(Emp_id) AS CharCode 
from Employee;

See the output.

Emp_name CharCode
Rohit Raj e
Shiva Rana f
Karan Kumar g
Suraj Bhakat h
Akash Cherukuri i

 

So, you can see from the output that the Character Code of Employee Id is returned under the column name CharCode.

SQL CHAR function can also be used as control characters.

CONTROL CHARACTER VALUE
Tab CHAR(9)
Line Feed CHAR(10)
Carriage return CHAR(13)

Multiple Integers

The char() function doesn’t support the multiple integers as arguments.

If you provide multiple integers, you’ll get an error.

See the following code example.

SELECT CHAR(67, 255) AS 'Result';

See the output.

The char function requires 1 argument(s).

Note that this is in the contrast to MySQL’s CHAR() function which allows you to provide multiple integers in the argument.

Out of Range Integers

The function also doesn’t support the integers outside a range of 1 to 255. If your argument is outside that range, the result is NULL.

See the following query.

SELECT CHAR(256) AS 'Result';

See the following output.

+----------+
| Result   |
|----------|
| NULL     |
+----------+

This is again in contrast to the MySQL’s CHAR() function, which accepts the integers larger than 255 in which case, they’re automatically converted into multiple result bytes.

Inserting Control Characters

See the following code.

SELECT 'Homer' + CHAR(13) + 'krunal@appdividend.com' AS 'Name/Email';

See the output.

+--------------+
| Name/Email   |
|--------------|
| Homer
krunal@appdividend.com              |
+--------------+

Here’s what it looks like if we remove the CHAR(13):

SELECT 'KRUNAL' AS 'Name', 'krunal@appdividend.com' AS 'Email';

See the output.

+--------+-----------------------+
| Name   | Email                 |
|--------+-----------------------|
| KRUNAL |krunal@appdividend.com |
+--------+-----------------------+

Finally, Char Function In SQL Tutorial is over.

Recommended Posts

ASCII Function In SQL

Stuff Function In SQL Tutorial

trim() Function In SQL

SQL Substring Function Example

SQL CONCAT Function Example

SQL Replace Function Example

SQL Check Constraint Example

SQL String Functions Example

SQL Try Catch Example

SQL NULL Functions Example

The post SQL Char Function Example | Char Function In SQL Tutorial appeared first on AppDividend.

Java String Contains Example | String contains() Method in Java

$
0
0
Java String Contains Example | String contains() Method in Java

Java String Contains Example | String contains() method in Java is today’s topic. Java contains() method was introduced in Java 1.5 release. It is used to find the sequence of characters in a given string. If that sequence is found it returns true, otherwise it returns false. Java String contains() function is used to check if the string contains the particular character sequence or not.

Java String Contains Example

The contains() method searches the sequence of characters in this string. It returns true if a sequence of char values are found in this string otherwise returns false.

Syntax

public boolean contains(CharSequence sequence)

The sequence: specifies the sequence of characters to be searched.

Implementation of this Method

The contains() method internally uses indexOf method, below the refers how to implement it:

public boolean contains(CharSequence s) 
{
    return indexOf(s.toString()) >= 0;
}

The contains() method internally uses String indexOf method, below code snippet, shows the contains() method definition.

Here conversion of CharSequence to a String takes place, and then the indexOf method is called which returns 0 or higher value if it finds the string. Otherwise, it returns -1.

Exception in this method

This method usually throws Null Pointer Exception if it finds that the length of the string is NULL.

Example of the string contains()

See the following code.

class contains {
    public static void main(String args[]) {
        String s1 = "Welcome to Appdividend";
        // prints true
        System.out.println(s1.contains("Welcome"));
        // prints false
        System.out.println(s1.contains("Hello"));
    }
}

See the output.

String contains() Method in Java

Now we will see one example of case sensitive method because contains() method is case sensitive.

See the following code.

class contains {
    public static void main(String args[]) {
        String s1 = "Welcome to Appdividend";

        // prints true
        System.out.println(s1.contains("Appdividend"));

        // prints false
        System.out.println(s1.contains("appdividend"));
    }
}

See the output.

Java String Contains

 

When to use Contains() method

It is the common case in programming when you want to check if the specific String contains the particular substring. For example, If you’re going to test if the String “The big red fox” contains the substring “red.”

This method is useful in such a situation.

See the following Java String contains() method in the if-else Loop.

public class IfExample {
    public static void main(String args[]) {
        String str1 = "Java string contains If else Example";
        // In If-else statements you can use the contains() method

        if (str1.contains("example")) {
            System.out.println("The Keyword :example: is found in given string");
        } else {
            System.out.println("The Keyword :example: is not found in the string");
        }
    }
}

Java String contains() with case insensitive check

In the case of insensitive check, we can change both the strings to either upper case or lower case before calling the contents() function.

"eleven".toLowerCase().contains("E".toLowerCase());

"eleven".toUpperCase().contains("E".toUpperCase());

See the output.

true
true

Java String contains() with CharSequence

Let’s see some examples of using String contains() method with StringBuffer, StringBuilder and, CharBuffer. All these are implementations of the CharSequence interface.

Also, note that CharBuffer is an abstract class, creating its instance is slightly different from other usual classes.

StringBuffer sb = new StringBuffer("User");
System.out.println(str.contains(sb)); // true


StringBuilder sb1 = new StringBuilder(sb);
System.out.println(str.contains(sb1)); // true

CharBuffer cb = CharBuffer.allocate(4);
cb.append('U');cb.append('s');cb.append('e');cb.append('r');
cb.clear();
System.out.println(cb); //User
System.out.println(str.contains(cb)); // true

Finally, the String contains() method in Java is over.

Recommended Posts

ArrayList in Java Tutorial

Java Enum Tutorial With Example

Java Multithreading Tutorial

Object-Oriented Programming in Java

Inheritance in Java

The post Java String Contains Example | String contains() Method in Java appeared first on AppDividend.

Relationalize Unstructured Data In AWS Athena with GrokSerDe

$
0
0

Managing the logs in a centralized repository is one of the most common best practices in the DevOps world. Application logs, system logs, error logs, and any databases logs also will be pushed into your centralized repository. You can use ELK stack or Splunk to visualize the logs to get better insights about it. But as a SQL guy, I wanted to solve this problem with Bigdata ecosystem(use SQL). As a part of that process, we can relationalize unstructured data in AWS Athena with the help of GrokSerDe.

Here S3 is my centralized repository. I know it will not scale like ElasticSearch, but why should I miss this Fun. For this use case, Im going to rationalize the SQL Server Error log in AWS Athena. Let’s take a look at the SQL server’s error log pattern.

2019-09-21 12:53:17.57 Server      UTC adjustment: 0:00
2019-09-21 12:53:17.57 Server      (c) Microsoft Corporation.
2019-09-21 12:53:17.57 Server      All rights reserved.
2019-09-21 12:53:17.57 Server      Server process ID is 4152.

Its looks like

yyyy-mm-dd space hh:mm:ss:ms space User space message

But sometimes, it has many lines like below.

2019-09-21 12:53:17.57 Server      Microsoft SQL Server 2017 (RTM) - 14.0.1000.169 (X64) 
  Aug 22 2017 17:04:49 
  Copyright (C) 2017 Microsoft Corporation
  Enterprise Edition: Core-based Licensing (64-bit) on Windows Server 2016 Datacenter 10.0 <X64> (Build 14393: ) (Hypervisor)
2019-09-21 12:53:17.57 Server      UTC adjustment: 0:00
2019-09-21 12:53:17.57 Server      (c) Microsoft Corporation.

If you see the 2nd, 3rd line we have the only message. And we know these all are just for information purpose, we’ll not get any useful information with that. Also as a part of Data cleansing, we should clean up some unwanted lines to make this relationalize.

I can consider the below format for my relationalize structure.

  • Year - Integer
  • Month - Integer
  • Day - Integer
  • Hour - Integer
  • Minute - Integer
  • Second - Integer
  • User - String
  • Message - String

We can convert this into a Grok pattern for this.

%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}\\s*%{TIME:time} %{LOG_LEVEL:user}\\s*( )*%{GREEDYDATA:message}

Create the table in Athena:

CREATE EXTERNAL TABLE `sql_errorlog`(
  `year` string , 
  `month` string , 
  `day` string , 
  `time` string , 
  `user` string , 
  `message` string )  
ROW FORMAT SERDE 
  'com.amazonaws.glue.serde.GrokSerDe' 
WITH SERDEPROPERTIES ( 
  'input.format'='%{YEAR:year}-%{MONTHNUM:month}-%{MONTHDAY:day}\\s*%{TIME:time} %{LOG_LEVEL:user}\\s*( )*%{GREEDYDATA:message}', 
'input.grokCustomPatterns'='LOG_LEVEL \[a-zA-Z0-9\]*') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://bhuvi-datalake/sql-error-log/'

The table got created. I used a custom pattern for pulling the user column.

Query the data:

SELECT *
FROM "default"."sql_errorlog" limit 10;

SELECT *
FROM "default"."sql_errorlog"
WHERE message LIKE '%shutdown%';

SELECT *
FROM "default"."sql_errorlog"
WHERE message LIKE '%Login failed%'

SELECT concat ('Server started at: ',year,'-',month,'-',day,' ',time) AS StartupTime
FROM "default"."sql_errorlog"
WHERE message LIKE '%Server process ID is%';

This is just a beginner guide, you can play around with windows logs, linux syslog, if you are a DBA then you may like to use this for MySQL, PostgreSQL, MongoDB logs.

BONUS: Regex Serde

If you are a developer, then regex might be easy for you. You can create a table with Regex Serde. Thanks to LeftJoin Who helped to write this Regex

CREATE EXTERNAL TABLE `bhuvi`(
  `date` string , 
  `time` string , 
  `user` string , 
  `message` string )
ROW FORMAT SERDE 
  'org.apache.hadoop.hive.serde2.RegexSerDe' 
WITH SERDEPROPERTIES ( 
  'input.regex'='(.*\\-.*\\-.*)\\s+(\\d+:\\d+:\\d+.\\d+)\\s+(\\S+)\\s+(.*?)$') 
STORED AS INPUTFORMAT 
  'org.apache.hadoop.mapred.TextInputFormat' 
OUTPUTFORMAT 
  'org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat'
LOCATION
  's3://bhuvi-datalake/bhuvi-1/'

References:

  1. Manage the SQL server workload with Customer Cloudwatch metrics.
  2. AWS Athena Grok Serde.

Join Pythian for Percona Live Europe 2019 Amsterdam

$
0
0

Percona Live is always a great opportunity to learn from the best and brightest in the open-source database community. This time, Percona Live Europe is being held at the Hilton Amsterdam Airport Schiphol, The Netherlands from September 30 to October 2, 2019.

Pythian will be present, as has been the case for the past few years, with some of our technical experts speaking on a variety of subjects and technologies.

Feel free to ping any of us during the conference breaks or community events, as we’ll be happy to answer any questions you have about anything open source, cloud, or data-related.

Here are some sessions you won’t want to miss:

Wednesday, October 2

9:00 AM – 10:00 AM
Maintenance for MongoDB Replica Sets
Room 10
Redundancy and high availability are the basis for all production deployments. With MongoDB, high availability is achieved with replica sets which provide automatic failover in case the primary goes down. In this session, we will review multiple maintenance scenarios that will include the proper steps for keeping the high availability while we perform the maintenance steps without causing downtime.

This session will cover database upgrades, OS server patching, hardware upgrades, network maintenance and more.

  • How MongoDB HA works
  • Replica sets components / deployment typologies
  • Database upgrades
  • System patching / upgrade
  • Network maintenance
  • Add / remove members to the replica set
  • Reconfiguring replica set members
  • Building indexes
  • Backups and restores

Speaker: Igor Donchovski


11:30 AM – 12:00 PM
Securing MySQL with Vault and Table Level Encryption
Room A
With all the personal information leaks, it is very important to make sure that your data is secure and protected. In this talk, I will go into, and demonstrate, how to secure your MySQL user accounts with Hashicorp Vault to do MySQL user account rotation and expiration. You can then integrate it with LDAP. There are a lot of users that do not use command line interface that may want to access these environments. This can all be done with Vaults’ built-in GUI interface. Finally, I will demonstrate how to encrypt your tables and store the key in Vault by base encoding your key and placing it into a KV store, or by just using the Percona keyring_vault plugin.

Speaker: Kevin Markwardt


2:30 PM – 3:30 PM
The DB is Broken. Now What?
Room 09
Sometimes the only piece of information you are given is that the database is not working correctly. What do you do now? Panic? Call Mom? But you’re the DBA. What you do next is crucial.

In this talk, we’ll cover the tools that you’ll use to determine what other agents may be working against the database performance. We’ll share our own experiences with crazy scenarios that stumped us, and the tools that we used to figure out the root cause.

Some examples include how systemd can ruin your day, NUMA imbalance, and issues unique to AWS, and GCP.

Speakers: Carmen Mason, Allan Mason, Ivan Groenewold


We look forward to seeing you at the show! Haven’t registered yet? Use CMESPEAK-IVAN code to get 20% off the registration fee.

Viewing all 18838 articles
Browse latest View live


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