Showing posts with label SQL. Show all posts
Showing posts with label SQL. Show all posts

Friday, August 5, 2016

Announcing: MySQL Utilities release-1.6.4 GA

The MySQL Utilities Team is pleased to announce a new GA release of MySQL Utilities. This release includes a number of improvements for usability, stability, and a few enhancements for better compatibility with MySQL 5.7. A complete list of all improvements can be found in our release notes.

Many Improvements!


This release represents a stable release of the product and is a significant improvement from the 1.5 release. Along with defect patches, we also include the following enhancements.

  • Support for MySQL 5.7 
  • New! Binlog Utilities:
    • mysqlbinlogpurge - purge old binary logs
    • mysqlbinlogrotate - rotate the binary log
    • mysqlbinlogmove - relocate binary log files
  • New! Replication Utilities: 
    • mysqlslavetrx - skip transactions on one or more slaves to solve errant transactions and consistency error
  • New! General Utilities: 
    • mysqlgrants - show grants for users
  • Improved functionality of --exclude option with SQL wildcards
  • Improved packaging in RPM and Windows distributions
  • Improved accuracy of calculated disk usage for mysqldiskusage
  • Improved packaging in RPM and Windows distributions
  • Improved output for mysqldbcompare and mysqldiff
  • Improved SSL support
  • The Replication utilities have undergone a number of improvements for new 5.7 features as well as quality and usability improvements.
  • The documentation has been improved including more descriptions of SSL connections and clarification of replication commands.
  • Finally, this release contains a host of minor improvements for quality and robustness

How Can I Download MySQL Utilities?


You can download MySQL Utilities 1.6.4 GA from the following link using one of the pre-built installation repositories including a source download.

http://dev.mysql.com/downloads/tools/utilities/

Where is the Documentation?


You can find online documentation for MySQL Utilities version 1.6 at:

http://dev.mysql.com/doc/index-utils-fabric.html

Thursday, March 31, 2016

Announcing MySQL Utilities 1.6.3 Beta!

The MySQL Utilities Team is pleased to announce a new beta release of MySQL Utilities. This release includes a number of improvements for usability, stability, and a few enhancements. A complete list of all improvements can be found in our release notes.

New Enhancements!


This release represents a stable release of the product. Along with several defect patches, we also include the following enhancements.

Improved support for MySQL 5.7
Improved functionality of --exclude option with SQL wildcards
Improved packaging in RPM and Windows distributions
Improved accuracy of calculated disk usage for mysqldiskusage
...and a host of minor improvements for quality and robustness


How Can I Download MySQL Utilities?


You can download MySQL Utilities 1.6.3 Beta from the following link using one of the pre-built installation repositories including a source download. Click on "Development Releases" to see the 1.6.3 release downloads.

http://dev.mysql.com/downloads/tools/utilities/

Where is the Documentation?


You can find online documentation for MySQL Utilities version 1.6 at:

http://dev.mysql.com/doc/index-utils-fabric.html

Tuesday, January 19, 2016

New Release! MySQL Connector/Arduino 1.1

The newest release of the MySQL Connector/Arduino library release-1.1 alpha is available for download. This new version represents a major step forward for the library in ease of use. Here are just a few of the important changes in this release.

  • Added to Library Manager : yes, you can download and install the library from the Arduino IDE now. Just open the Library Manager and search for "MySQL".
  • More Example Sketches : there are many more example sketches of how to use the new library from basic connections to complex queries and more! 
  • Redesigned Classes : the library has been redesigned with new classes making it much easier to use a wider variety of shields and modules. Now, you pass in the Client class for your shield and so long as it adheres to the Ethernet.Client primitive, you can use any library to initiate the connector. No more #defines!
  • Better Memory Management : the new classes permit you to manage memory easier by allocating the MySQL_Query class dynamically leaving memory cleanup for the delete operation. No more free_* methods!
  • It's on GitHub! : yes, the code is now on GitHub making it much easier to log and track issues. See GitHub Repo.

Notes on Usage


If you have been using the previous versions of MySQL Connector/Arduino (1.0.4 and prior), do not despair as the old version remains in Launchpad and will be be left there for some time. Best of all, the new version does not cause conflicts with any of your existing sketches. That is, your existing sketches will not be affected by installing the new library.

However, if you want to use the newest version in your existing sketches, you will have to change a few things. Please see the section entitled "Changes from Previous Versions" in the reference manual located in the extras folder of the library source code.

How do I get it?


As mentioned, you can simply open the Library manager in the Arduino IDE from the Sketch->Include Library->Manage Libraries menu. This opens the Library Manager. In the filter your search box, enter "MySQL" then choose the connector and click Install. In seconds, the new library is installed and ready for use. Cool, eh?



You can also check the Library Manager periodically for updates to this or any of the libraries you have installed.

Of course, if you want to download the source code directly, you can find it on GitHub at GitHub Repo.

How do I use the library?


There is extensive documentation on how to use the library in the reference manual located in the extras folder. The document is named MySQL_Connector_Arduino_Reference_Manual.pdf.

What if I have Questions?


You can post questions to this blog or if you find a defect, open an issue of GitHub. However, before you do either, please read the documentation - even if you've been using the older versions as much has changed!

Enjoy!

Thursday, April 3, 2014

New! MySQL Utilities release-1.4.2-RC

The MySQL Utilities Team is pleased to announce the latest release candidate (RC) release of MySQL Utilities. This release includes a number of improvements for useabilty, stability, and a few enhancements. A complete list of all improvements can be found in our release_notes.

New Utilities!


We have also included two new utilities.
  • The mysqlrplsync utility was added, which checks data consistency between servers in a replicated setup. 
  • The mysqlrplms utility was added, which provides round-robin multi-source replication (a slave server continually cycles through multiple masters in order to store a consolidated data set).

How Can I Download MySQL Utilities?


You can download MySQL Utilities 1.4.2 from the following link using one of the pre-built installation repositories including a source download. Click on the Development Releases tab.

http://dev.mysql.com/downloads/tools/utilities/

Where is the Documentation?


You can find online documentation for MySQL Utilities version 1.4 at:

http://dev.mysql.com/doc/index-gui.html

Wednesday, April 2, 2014

Announcing MySQL Connector/Arduino 1.0.2 Beta

I've completed a new release of the Connector/Arduino! The new release contains some major improvements with memory handling.
  • The library has been trimmed to save memory.
    • Static strings moved to PROGMEM strings
    • Unused structures removed (e.g. ok_packet)
    • Moved two more methods to optional compilation
  • The WITH_SELECT is turned *OFF* by default. If you want to use select queries, be sure to uncomment this in the mysql.h file.
  • Added a CHANGES.txt file to track changes between releases.

Memory, What Memory?


If you have used previous versions of the connector in medium to large sketches or have long query strings or even many variables, chances are you have hit the memory limit for your wee Arduino board.

This can manifest itself in a number of ways. Most notably, the sketch may work for you until you add more code or more sensors in which it can fail to connect to the server. It can also exhibit random reboots or random freezes. If this is happening to you, it is most likely a memory issue.

That is, the old version of the connector consumed nearly 70% of available dynamic memory - the memory used for variables. When the Arduino exceeds its memory limit, sketches will exhibit strange behavior or the board may reboot.

Many people have encountered this so I've worked hard to try and squeeze more memory out of the connector. Which isn't easy considering it must keep a buffer of the data being sent to (or received from) the server.

Let's see an example. The old version of the connector (1.0.1b), when compiled with the hello_mysql example for a Uno, consumes about 68% of available dynamic memory leaving only 637 bytes for your own variables. That's fine for a simple sketch but if you want to do complex queries building INSERT statements from several sensors or including other libraries for additional features (like an LCD), you're not going to be happy.

While you can (and should) limit your memory use and even make use of PROGMEM for your static strings (and calling cmd_query_P()), it still isn't enough free memory for larger sketches. The following is the compile message generated by the beta release of the Arduino IDE (1.5.4).

Sketch uses 22,376 bytes (69%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,411 bytes (68%) of dynamic memory, leaving 637 bytes for local variables. Maximum is 2,048 bytes.

 

Now, with the new version of the library and SELECT turned on, the connector consumes only 58% of dynamic memory as shown below. While that is better, it isn't quite where we need to be.

Sketch uses 22,152 bytes (68%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,197 bytes (58%) of dynamic memory, leaving 851 bytes for local variables. Maximum is 2,048 bytes.

 

If we turn off the SELECT feature with the new version, we get a little better.

Sketch uses 20,736 bytes (64%) of program storage space. Maximum is 32,256 bytes.
Global variables use 1,064 bytes (51%) of dynamic memory, leaving 984 bytes for local variables. Maximum is 2,048 bytes.

 

Ah, now we're cooking. The dynamic memory usage is down to 51%. Much better.


Choosing the Right Board


One of the things users new to the connector have struggled with is choosing the right Arduino board for their project. The connector is a non-trivial library that consumes (relatively) a lot of memory. If you want to write a really big sketch using lots of variables, strings, etc., you will need to use a board with more memory.

This is especially true when you combine the connector with other libraries like those made for some sensors, shields, and more. The combined memory for the connector and the other libraries can consume a lot of dynamic memory leaving you very little to use for your own variables.

While most solve the problem by switching to a Mega board, that has its own issues because some of the pins differ from the smaller (memory-wise, not size-wise) boards. A few Google searches will quickly find solutions to these problems (hint: software serial).

So which board should you choose? I've done some research for you and have compiled a simple MySQL sketch using the new version of the connector on a variety of boards. The following lists the memory usage reports from the Arduino Beta IDE. In this case, the compilations are with SELECT turned off (which is the new default).

  • Duemilanove, Uno : 1,064 bytes (51%) of dynamic memory, leaving 984 bytes for local variables
  • Leonardo : 1,028 bytes (40%) of dynamic memory, leaving 1,532 bytes for local variables
  • Mega 2560 : 1,550 bytes (18%) of dynamic memory, leaving 6,642 bytes for local variables
  • Yun : 1,028 bytes (40%) of dynamic memory, leaving 1,532 bytes for local variables

As you can see, using the older Uno-style boards are going to limit your ability to write complex sketches with many variables, logic, etc. However, a Leonardo or even a Yun board may be a better choice especially if you run out of memory on the Uno-style board. Of course, the Mega is the best choice if your sketch is going to be very complex or if you need to store a lot of values in memory or use other, large libraries.

Conclusion


I hope this new version solves many of your problems with memory. I've tried to shrink it down as much as I can without radical changes. I believe the majority of the connection failures and freezes will be solved with this new version. Please feel free to provide feedback on this blog or (better) on the Oracle Connector/Arduino forum.

http://forums.mysql.com/list.php?175

Thursday, December 19, 2013

New! MySQL Utilities release-1.3.6 GA

The MySQL Utilities Team is pleased to announce the latest GA release of MySQL Utilities. This release includes a number of improvements for usability, stability, and a few enhancements. We have also included a performance upgrade for exporting, importing, and copying databases.

Improvements


The following highlights a few of the more significant improvements.

* mysqldbexport, mysqldbimport, and mysqldbcopy have multiprocessing support that allows for much improved performance
* mysqlfrm can now generate a .frm file with storage engine substitution
* Mac OS X packages added!
* mysqlserverinfo now includes the log files (error, general, slow)
* mysqlprocgrep can now search and kill processes by id
* mysqlmetagrep can now search the body of routines with the new --body option
* all utilities report license type with --version and --help
* all utilities have the new --license option to view the license text
* the mysqluc now reports errors with clearer text and tags the message with the name of the utility that returned the error
* mysqlindexcheck now warns user if there is not enough information to calculate best/worst indexes
* rpm, debian, and msi packages will update/remove old versions automatically when installing a newer version
* the documentation is now a separate reference manual (see link below)

The following spotlight some of the more important enhancements.

Multiprocessing with mysqldbexport, mysqldbimport, and mysqldbcopy


The performance of the mysqldbcopy, mysqldbexport and mysqldbimport utilities has been significantly improved. Moreover, a new --multiprocess option was added to allow concurrent execution making the most of the available CPU resources (the number of CPU cores).

Note: the --thread option in mysqldbcopy was replaced by the --multiprocess option.

Multiprocessing is applied at different levels according to the operating system. The utilities mysqldbcopy and mysqldbexport allow multiprocessing at the table-level for non-Windows systems and at the database-level for Windows system. The mysqldbimport utility allows multiprocessing at the file-level independently from the OS.

Other more specific options were also added for performance reasons for the other utility. A new --output-file option was added to mysqldbexport to specify a file to store the generated output which allows faster output than sending messages to the terminal.

Two additional additional options are now available in mysqldbimport: 1) --autocommit to enable autocommit for each operation because now by default a single commit is performed at the end of importing each file which is much faster, and 2) --max-bulk-insert to adjust the maximum number of inserts in a bulk, following the improved bulk insert support that is now provided.

Create New .frm Files with New Storage Engine


The mysqlfrm utility allows you to use the --new-storage-engine and the new --frmdir option to provide a directory to store the new .frm files. This feature is useful for those who want to recover the CREATE statement from existing .frm files and change the storage engine without having to launch the server. Try it out!

Mac OS X Installer


Yes, we now have a Mac OS X package installer. If you install Utilities with this installer, you will need to either use Connector/Python version 1.1.4 or later (which has a Mac OS X installer too) or use the Connector/Python 1.0.8 or later source code package and install manually.

How Can I Download MySQL Utilities?


You can download MySQL Utilities 1.3.6 from the following link using one of the pre-built installation repositories including a source download.

http://dev.mysql.com/downloads/tools/utilities/

If you are a commercial customer, you can download MySQL Utilities from the following link:

https://edelivery.oracle.com/

MySQL Utilities is also available on Lauchpad as a source download at:

https://code.launchpad.net/mysql-utilities

Where is the Documentation?


You can find online documentation for MySQL Utilities version 1.3 at:

http://dev.mysql.com/doc/index-gui.html

Wednesday, October 23, 2013

Introducing MySQL Connector/Arduino 1.0.0 beta

There is a new release of the Connector/Arduino on Launchpad! See https://launchpad.net/mysql-arduino. The new version supports a number of refinements and a few new features. These include:
  • Improved support for processing result sets
  • Conditional compilation to omit result set handling features to save program space
  • Support for the Arduino WiFi shield
  • New version() method to check version of the connector
  • Simplified download (no more patching SHA1!)

So What is It?


If you have never heard of Connector/Arduino, it is simply a library designed to allow the Arduino platform to connect to and issue queries to a MySQL Database server.

Simply add an Ethernet shield to your Arduino and use the library to connect your Arduino to a MySQL database server. Yes, no more web-based hand waving or third party systems! Cool.

New Feature : Improved Support for Result Sets


In the previous version of the connector, there was a method named show_results() which demonstrated how to read result sets (rows returned from the server from a SHOW or SELECT query).

Unfortunately, this method was too obtuse to be of any use to all but the most devoted connector fan (you had to know the source code really well). Perhaps worse, you had to modify the library directly to use the methods demonstrated.

Why was it like that? Simply because I felt SELECT queries would be very rare and used by only a very small number of people. I was wrong. Live and learn, eh?

The good news is the new version has additional methods that can be called from outside the library making it much, much easier to get results from your database. Let's see how to do this.

Example: Getting a Lookup Value


I think the most popular request for supporting SELECT queries was to allow for an easy way to query the database for a lookup value. Since lookup queries are (or should be) designed to return exactly one row, we can simplify the code as follows.

Recall when the MySQL server returns a result set, the first thing returned is a list of the columns in the result set. Next are the rows. So we must process the columns first.

  // SELECT query for lookup value (1 row returned)
  // Here we get a value from the database and use it.
  long head_count = 0;
  my_conn.cmd_query(QUERY_POP);
  // We ignore the columns but we have to read them to get that data out of the queue
  my_conn.get_columns();
  // Now we read the rows.
  row_values *row = NULL;
  do {
    row = my_conn.get_next_row();
    // We use the first value returned in the row - population of NYC!
    if (row != NULL) {
      head_count = atol(row->values[0]);
    }
  } while (row != NULL);
  // We're done with the buffers so Ok to clear them (and save precious memory).
  my_conn.free_columns_buffer();
  my_conn.free_row_buffer();
  // Now, let's do something with the data.
  Serial.print("NYC pop = ");
  Serial.println(head_count);


In this example, I query the database for the population of New York City (nervemind the validity of that value), then use the value by printing it out. Notice the basic structure is still there - read columns then read rows but in this case we ignore the columns because we don't need that data. We still need the free_*_buffer() calls to free memory however. I explain these methods in the next example.

Example: Processing Result Sets


The next most popular request for supporting result queries was being able to loop through a result set and do something with the data. In this example, I create a method in my sketch to execute the query and process the results. Let's look at the code first.

/**
 * do_query - execute a query and display results
 *
 * This method demonstrates how to execute a query, get the column
 * names and print them, then read rows printing the values. It
 * is a mirror of the show_results() example in the connector class.
 *
 * You can use this method as a template for writing methods that
 * must iterate over rows from a SELECT and operate on the values read.
 *
 */
/*
void do_query(const char *q) {
  column_names *c; // pointer to column values
  row_values *r;   // pointer to row values

  // First, execute query. If it returns a value pointer,
  // we have a result set to process. If not, we exit.
 

  if (!my_conn.cmd_query(q)) {
    return;
  }

  // Next, we read the column names and display them.
 
  // NOTICE: You must *always* read the column names even if
  //         you do not use them. This is so the connector can
  //         read the data out of the buffer. Row data follows the
  //         column data and thus must be read first.
 

  c = my_conn.get_columns();
  for (int i = 0; i < c->num_fields; i++) {
    Serial.print(c->fields[i]->name);
    if (i < c->num_fields - 1) {
      Serial.print(",");
    }
  }
  Serial.println();

  // Next, we use the get_next_row() iterator and read rows printing
  // the values returned until the get_next_row() returns NULL.
 

  int num_cols = c->num_fields;
  int rows = 0;
  do {
    r = my_conn.get_next_row();
    if (r) {
      rows++;
      for (int i = 0; i < num_cols; i++) {
        Serial.print(r->values[i]);
        if (i < num_cols - 1) {
          Serial.print(", ");
        }
      }
      Serial.println();
 

      // Note: we free the row read to free the memory allocated for it.
      // You should do this after you've processed the row.
 

      my_conn.free_row_buffer();
    }
  } while (r);
  Serial.print(rows);
  Serial.println(" rows in result.");

  // Finally, we are done so we free the column buffers
 

  my_conn.free_columns_buffer();
}


So what's going on here? Notice how the code is structured to execute the query and if there are results (cmd_query() does not return NULL), we read the column headers. Why? Because the server always sends the column data back first for every result set.

The return from the get_columns() method is a structure that contains an array of field structures. Here are the structures:

// Structure for retrieving a field (minimal implementation).
typedef struct {
  char *db;
  char *table;
  char *name;
} field_struct;

// Structure for storing result set metadata.
typedef struct {
  int num_fields;     // actual number of fields
  field_struct *fields[MAX_FIELDS];
} column_names;


Notice the column_names structure has a fields array. Use that array to get information about each field in the form of the field_struct (see above) structure. In that structure, you will be able to get the database name, table name, and column name. Notice in the example I simply print out the column name and a comma after each except the last column.

Next, we read the rows using a special iterator named get_next_row() which returns a pointer to a row structure that contains an array of the field values as follows:

// Structure for storing row data.
typedef struct {
  char *values[MAX_FIELDS];
} row_values;


In this case, while get_next_row() returns a valid pointer (not NULL indicating a row has been read), we access each field and print out the values.

You may be wondering what is MAX_FIELDS? Well, it is an easy way to make sure we limit our array to a maximum number of columns. This is defined in mysql.h and is set to 32. If you want to save a few bytes, you can change that value to something lower but beware: if you exceed that value, your code will wander off into la-la-land (via an unreferenced pointer). There is no end of array checking so tread lightly.

Notice also there are calls to free_row_buffer() and free_columns_buffer(). These are memory cleanup methods needed to free any memory allocated when reading columns and row values (hey - we got to put it somewhere!).

We call the free_row_buffer() after we are finished processing the row and the free_columns_buffer() at the end of the method. If you fail to add these to your own query handler method, you will run out of memory quickly.

Why is it a manual process? Well, like the MAX_FIELDS setting, I wanted to keep it simple and therefore save as much space as possible. Automatic garbage collection would have added a significant amount of code. Likewise array bound checking would have add a bit more.

You can use this method as a template to build your own custom query handler. For example, instead of printing the data to the serial monitor, you could display it in an LCD or perhaps use the information in another part of your sketch.


New Feature : Conditional Compilation


If you find you do not need the result set support, you can use conditional compilation to remove the methods and code from the connector. This can save you about 2k of program memory!

To do this, simply edit the mysql.h file and comment out this code:

//#define WITH_SELECT  // Comment out this for use without SELECT capability
                       // to save space.


This will tell the compiler to ignore key result set handling methods and code from the connector.

If you do this but find there are methods suddenly missing (via compilation errors), check your sketch to make sure you are not using show_results(), get_columns(), get_next_row(), and similar methods. This is because with the SELECT code turned off, these methods no longer exist in the compiled library. Uncomment the #define WITH_SELECT to add them back.

New Feature : Support for WiFi Shield


To use the WiFi shield, you need only make a few changes to your sketch and a minor change to the library.

Note: You will need to download the WiFi library and install it to use the WiFi shield. See http://arduino.cc/en/Main/ArduinoWiFiShield for more information.

First, add the #include for the WiFi library *before* the include for the connector (mysql.h).

#include <WiFi.h>  // Use this for WiFi
#include <mysql.h>


Next, setup your choice of WiFi connection options in your setup() method. While you're there, comment out the Ethernet.begin() call.

// WiFi card example
char ssid[] = "my_lonely_ssid";
char pass[] = "horse_no_name";

void setup() {
  Serial.begin(115200);
  while (!Serial); // wait for serial port to connect. Needed for Leonardo only

//  Ethernet.begin(mac_addr);

  // WiFi section
  int status = WiFi.begin(ssid, pass);
  // if you're not connected, stop here:
  if ( status != WL_CONNECTED) {
    Serial.println("Couldn't get a wifi connection");
    while(true);
  }
  // if you are connected, print out info about the connection:
  else {
    Serial.println("Connected to network");
    IPAddress ip = WiFi.localIP();
    Serial.print("My IP address is: ");
    Serial.println(ip);
  }
...


Lastly, you need to make one small change to the connector itself. Open the mysql.h file and uncomment these two lines:

#define WIFI       // Uncomment out this for use with the WiFi shield
#include <WiFi.h>  // Uncomment out this for use with the WiFi shield


This tells the connector to use the conditional compilation sections to turn on support for the WiFi shield.

New Feature : version() method


I've added a method to return the version of the connector as a string. If you don't have this method, you're using an old version of the connector. As more releases of the connector occur, this method will be key in diagnosing problems or checking for support of certain features.

(Somewhat) New Feature : Single File Download


This was actually added to the Launchpad site for the previous version of the connector (version 1.0.0 alpha). But I'm making it the default download method from now on. You can still get the code the old way (by using bzr to clone the tree) but the single file download makes it much easier.

Simply download the file, extract it, then place the two folders; mysql_connector and sha1 in your libraries folder then restart the IDE. Install done!

I hope you enjoy the new enhancements.

Tuesday, October 22, 2013

Announcing: New Forum for Connector/Arduino!

Due to the growing popularity of Connector/Arduino, the moderator of MySQL Forums has created a forum for us to meet up and discuss the connector. Yippie!

http://forums.mysql.com/list.php?175

While the forum has been started very recently, I expect it will grow quickly as people discover the connector for the first time and experienced users find new and interesting ways to use it. I hope to moderate the new forum periodically to answer questions and respond to posts. See you there!

Note: you need an account to write to the forum. Click on "register" in the upper right hand corner of the forum page to create an account if you do not already have one.


Thursday, August 22, 2013

Announcing MySQL Utilities release-1.3.4 GA

The MySQL Utilities Team is pleased to announce the latest GA release of
MySQL Utilities. This release marks a milestone of concentrated effort to
expand the use of utilities in more diverse installations through improved
robustness, error handling, and quality.

Many Improvements


There are number such enhancements in this release. In this post we will
highlight a few of the more significant improvements.
  • (new utility) MySQL .frm Reader (mysqlfrm) - read .frm files and generate CREATE statements with or without a server connection.
  • (revised) improved documentation including a section on example administrative tasks - see http://dev.mysql.com/doc/workbench/en/mysql-utilities.html
  • MySQL Utilities is packaged for .msi, .rpl, .deb platforms and source .tar/.zip
  • You can run mysqlfailover as a daemon on POSIX systems
  • Improved accuracy redundant index checking algorithm for mysqlindexcheck
  • Improved accuracy for comparing databases with mysqldbcompare
  • The --exclude option for mysqldbcopy and mysqldbexport now accept database patterns
  • Improved quoting of database, table, index names in SQL generation
  • External script return code checking for mysqlfailover, mysqlrpladmin
  • Slave thread state included in verbosity output of mysqlrplshow
  • The mysqldbimport utility can now read raw CSV files with headers
...and that's just a few of the many improvements in this release. While many
of these improvements have been filtering into the 1.2.X release over the last
year, this release marks the first GA in that time frame.

How Can I Download MySQL Utilities?


You can download MySQL Utilities 1.3.4 from
http://dev.mysql.com/downloads/tools/utilities/ using one of the pre-built
installation repositories including a source download. MySQL Utilities is also
available on Lauchpad as a source download at
https://code.launchpad.net/mysql-utilities.

Thursday, July 14, 2011

Comparing Databases with mysqldbcompare

If you have two or more database servers containing the same data, how do you know if the objects are identical. Furthermore, how can you be sure the data is the same on all of the servers? What is needed is a way to determine if the databases are in synch - all objects are present, the object definitions are the same, and the tables contain the same data. Synchronizing data can become a nightmare without the proper tools to quickly identify differences among objects and data in two databases. Perhaps a worst case (and more daunting) is trying find data that you suspect may be different but you don’t have any way of finding out.

This is where the new 'mysqldbcompare' utility comes in handy. The mysqldbcompare utility uses the mysqldiff functionality (mysqldiff allows you to find the differences in object definitions for two objects or a list of objects in two databases) and permits you to compare the object definitions and the data among two databases. Not only will it find the differences among database objects and their definitions, it will also find differences in the data!

The databases can reside on the same server or different servers. The utility performs a consistency check to ensure two databases are the same defined as having the same list of objects, identical object definitions (including object names), and for tables the same row counts and the same data.

Some scenarios where mysqldbcompare can be employed include:

  • checking master and slave for consistency
  • checking production and development databases for consistency
  • generating a difference report for expected differences among new and old data
  • comparing backups for differences
Running the Utility

Let us take a look at the utility in action. Below are two examples of the utility comparing what should be the same database on two servers. I am using a simple detail shop inventory database used to manage supplies. It consists of two tables (supplier, supplies) and three views (cleaning, finishing_up, and tools).

In the first example, we see an example where the databases are consistent. When you examine the output, you will see each object is inspected in three passes. First, the object definitions are compared. Any discrepancies would be displayed as a difference in their CREATE statements. If the object is a table, a row count test is performed followed by a comparison of the data. Surely, if the row count test fails we know the data check will fail.

Note: This is the same output (and indeed the same code) that is used for mysqldiff. The mysqldbcompare utility has all of the same features with respect to difference type presented (unified, differ, and context) which you can select with the same option named ‘--difftype’.

mysqldbcompare --server1=root@localhost --server2=root@backup_host:3310 inventory:inventory
# server1 on localhost: ... connected.
# server2 on localhost: ... connected.
# Checking databases inventory on server1 and inventory on server2


Defn Row Data
Type Object Name Diff Count Check
---------------------------------------------------------------------------
TABLE supplier pass pass pass
TABLE supplies pass pass pass
VIEW cleaning pass - -
VIEW finishing_up pass - -
VIEW tools pass - -


Databases are consistent.


# ...done

Normally, the mysqldbcompare utility will stop on the first failed test. This default means you can run the utility as a safeguard on data that you expect to be consistent. However, if you suspect or know there will be differences in the database objects or data and want to run all of the checks, you can use the ‘--run-all-tests’ option. This option will run the tests on all objects even if some tests fail. Note that this does not include system or access errors such as a down server or incorrect login - those errors will cause the utility to fail with an appropriate error message.

In the second example, we expect the databases to be different and we want to know which data is different. As you can see, the utility found differences in the object definitions as well as differences in the data. Both are reported.

mysqldbcompare --server1=root@localhost --server2=root@backup_host:3310 inventory:inventory --run-all-tests
# server1 on localhost: ... connected.
# server2 on localhost: ... connected.
# Checking databases inventory on server1 and inventory on server2


WARNING: Objects in server1:inventory but not in server2:inventory:
VIEW: finishing_up
VIEW: cleaning


Defn Row Data
Type Object Name Diff Count Check
---------------------------------------------------------------------------
TABLE supplier pass FAIL FAIL


Row counts are not the same among inventory.supplier and inventory.supplier.


Data differences found among rows:
--- inventory.supplier
+++ inventory.supplier
@@ -1,2 +1,2 @@
code,name
-2,Never Enough Inc.
+2,Wesayso Corporation


Rows in inventory.supplier not in inventory.supplier
code,name
3,Never Enough Inc.


TABLE supplies pass FAIL FAIL


Row counts are not the same among inventory.supplies and inventory.supplies.


Data differences found among rows:
--- inventory.supplies
+++ inventory.supplies
@@ -1,4 +1,4 @@
stock_number,description,qty,cost,type,notes,supplier
-11040,Leather care,1,9.99,other,,1
-11186,Plastic polish,1,9.99,polishing,,1
-11146,Speed shine,1,9.99,repair,,1
+11040,Leather care,1,10.00,other,,1
+11186,Plastic polish,1,10.00,polishing,,1
+11146,Speed shine,1,10.00,repair,,1


Rows in inventory.supplies not in inventory.supplies
stock_number,description,qty,cost,type,notes,supplier
11104,Interior cleaner,1,9.99,cleaning,,1
11056,Microfiber and foam pad cleaner,1,9.99,cleaning,,1
11136,Rubber cleaner,1,9.99,cleaning,,1
11173,Vinyl and rubber dressing,1,9.99,cleaning,,1
11106,Wheel cleaner,1,9.99,cleaning,,1
11270,Carpet cleaner,1,9.99,cleaning,,1


Rows in inventory.supplies not in inventory.supplies
stock_number,description,qty,cost,type,notes,supplier
11269,Microfiber spray on car wash towel,3,16.99,cleaning,,1
11116,Microfiber wax removal towel,3,16.99,waxing,,1
10665,Glass polish pad,3,10.00,polishing,,1


VIEW tools FAIL - -


--- inventory.tools
+++ inventory.tools
@@ -1,1 +1,1 @@
-CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `inventory`.`tools` AS select `inventory`.`supplies`.`stock_number` AS `stock_number`,`inventory`.`supplies`.`description` AS `description`,`inventory`.`supplies`.`qty` AS `qty`,`inventory`.`supplies`.`cost` AS `cost`,`inventory`.`supplies`.`type` AS `type`,`inventory`.`supplies`.`notes` AS `notes`,`inventory`.`supplies`.`supplier` AS `supplier` from `inventory`.`supplies` where (`inventory`.`supplies`.`type` = 'tool')
+CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `inventory`.`tools` AS select `inventory`.`supplies`.`stock_number` AS `stock_number`,`inventory`.`supplies`.`description` AS `description`,`inventory`.`supplies`.`qty` AS `qty`,`inventory`.`supplies`.`cost` AS `cost`,`inventory`.`supplies`.`type` AS `type`,`inventory`.`supplies`.`notes` AS `notes`,`inventory`.`supplies`.`supplier` AS `supplier` from `inventory`.`supplies` where (`inventory`.`supplies`.`type` in ('tool','other'))


Database consistency check failed.

Take a moment to read through the report above. At the top of the report (the first object tested), we see a critical error in the suppliers table. Here we can see that there are two different names for the same supplier_id. All relational database theory aside, that could spell trouble when it comes time to reorder supplies.

Notice the report for the supplies table. In this example, the utility identified three rows that were different among the two databases. It also identified rows that were missing from either table. Clearly, that could help you diagnose what went wrong where in your application (or your data entry).

Lastly, we see a possible issue with the tools view. Here the view definition differs slightly. Depending the use of the view this may be acceptable but it is nice to know nonetheless.

What Does This All Mean?

If data consistency is important to you or if you need a way to quickly determine the differences among data in two databases, the mysqldbcompare utility is a great addition to your toolset. But don’t take my word for it - try it out yourself.

Download and Try It Out!

The MySQL Utilities project is written in Python and is a component of the MySQL Workbench tool. You can download the latest release of the MySQL Workbench here:

http://dev.mysql.com/downloads/workbench/

There are some limitations in this first release. Currently, if the storage engines differ among the tables in the compare, the object definitions will show this difference – which is exactly what you would expect. However, the utility will stop and report the object definition test as a failure. You can still run the data consistency check by using the --force option which instructs the mysqldbcompare utility to run all tests unless they fail from an internal exception (for example, the table files are corrupt).

Got Some Ideas or Want to See New Features?

One really cool feature would be if the utility generate SQL statements for synchronizing the data and objects. Would this be something you would want to see incorporated?

If you’re intrigued by this new utility and in your course of use find new features or new uses that you would like to see incorporated in future revisions, please email me and let me know!

Related Material

Th latest MySQL Utilities development tree (including mysqldbcompare) can be found here:

https://launchpad.net/mysql-utilities