Archive for the ‘tutorial’ Category

Building MySQL Workbench from sources on Ubuntu/Debian

Октябрь 17th, 2011

To build MySQL Workbench one would need to install dependencies, fetch source code, configure it and actually do a build.

Note: On a Core2 Quad 2.4 GHz and a 4G of RAM it takes aout 30-40 minutes to build Workbench. Also it uses about 4.2G of hdd space to build.

Here are steps to build Workbench on Ubuntu/Debian:

1) install deps. It is better to use terminal. The command to install deps is below:

sudo apt-get install build-essential autoconf automake libtool libzip-dev libxml2-dev libsigc++-2.0-dev libglade2-dev libgtkmm-2.4-dev libglu1-mesa-dev libmysqlclient15-dev uuid-dev liblua5.1-dev libglitz-dev libglitz-glx-dev libpcre3-dev g++ libglade2-dev libgnome2-dev python-pexpect libboost-dev libsqlite3-dev python-dev libgnome-keyring-dev libctemplate-dev

2) Get source code from http://www.mysql.com/downloads/workbench/

3) unpack downloaded archive and run autogen.sh from the unpacked directory. The actual invokation may vary, for example:

./autogen.sh –prefix=/usr/local

or

./autogen.sh –prefix=/opt/

–prefix tells coniguration utility that install of Workbench should be done using the pivot directory.

Upon successfull completion ./autogen.sh should generate Makefiles.

4) Build the tool.

That is simply make. If you have more than one core the you may like to use parallel build. For example, on a 4 cores box it is advised to use make -j5 install, on 2 cores – make -j3 install.

When built and installed, the directory which contains source files can be deleted.

UPD: to apply patch, get in the source directory and do patch -p0 < 5.2.35-ubuntu_11_10_compile_fix.patch

 


PlanetMySQL Voting: Vote UP / Vote DOWN

Building MySQL Workbench from sources on Ubuntu/Debian

Октябрь 17th, 2011

To build MySQL Workbench one would need to install dependencies, fetch source code, configure it and actually do a build.

Note: On a Core2 Quad 2.4 GHz and a 4G of RAM it takes aout 30-40 minutes to build Workbench. Also it uses about 4.2G of hdd space to build.

Here are steps to build Workbench on Ubuntu/Debian:

1) install deps. It is better to use terminal. The command to install deps is below:

sudo apt-get install build-essential autoconf automake libtool libzip-dev libxml2-dev libsigc++-2.0-dev libglade2-dev libgtkmm-2.4-dev libglu1-mesa-dev libmysqlclient15-dev uuid-dev liblua5.1-dev libglitz-dev libglitz-glx-dev libpcre3-dev g++ libglade2-dev libgnome2-dev python-pexpect libboost-dev libsqlite3-dev python-dev libgnome-keyring-dev libctemplate-dev

2) Get source code from http://www.mysql.com/downloads/workbench/

3) unpack downloaded archive and run autogen.sh from the unpacked directory. The actual invokation may vary, for example:

./autogen.sh –prefix=/usr/local

or

./autogen.sh –prefix=/opt/

–prefix tells coniguration utility that install of Workbench should be done using the pivot directory.

Upon successfull completion ./autogen.sh should generate Makefiles.

4) Build the tool.

That is simply make. If you have more than one core the you may like to use parallel build. For example, on a 4 cores box it is advised to use make -j5 install, on 2 cores – make -j3 install.

When built and installed, the directory which contains source files can be deleted.

UPD: to apply patch, get in the source directory and do patch -p0 < 5.2.35-ubuntu_11_10_compile_fix.patch

 


PlanetMySQL Voting: Vote UP / Vote DOWN

MySQL Workbench: Introducing Utilities

Декабрь 9th, 2010

MySQL has the well earned reputation for ease-of-use and “15-minutes-to-success”, since we continually focus making the server easy to use. MySQL Workbench provides the visual tools for database design, development, and administration. However, many DBAs prefer using the command-line, and there are many tasks that require the creation scripts for doing the job.

To make it easier to work with the server, the latest release of the MySQL Workbench—version 5.2.31—contain a set of Python scripts intended to make the life easier for DBAs by providing easy-to-use utilities for common tasks, which were introduced in the blog MySQL Workbench: Utilities. The set currently consists of just a few utilities, but will expand over time.

The utilities available in the Workbench are:

mysqldbcopy
Copy databases between servers.
mysqldbexport
Export databases to a file in different formats, including: SQL, comma-separated files, and tab-separated files (and some more).
mysqldbimport
Import object definitions and/or data from a file—in different formats, similar to mysqldbexport—into a database.
mysqlindexcheck
Check for redundant or duplicate indexes on a list of tables or databases. It can also generate DROP statements to
remove redundant indexes.
mysqlmetagrep

Search MySQL servers for objects containing fields matching a pattern.

mysqlprocgrep

Search MySQL servers for processes matching a pattern and perform actions.

mysqlreplicate

Setup replication between two servers.

mysqlserverclone

Start a new instance of a server to experiment with. This is used to test the utilities, but can be used whenever you need to set up a scratch server to test something.
mysqluserclone

Copy a MySQL user to one or more new users on another server

Finding stuff on servers with ease

In order to search for various things on servers—for example, searching objects and processes—there are two commands that can be used: mysqlprocgrep and mysqlmetagrep. The name “grep” is borrowed from Unix where the grep(1) commands that can be used to search inside files, but in this case you can search among processes and inside metadata on a server.

Example: searching processes using mysqlprocgrep

With mysqlprocgrep you can find all processes that match certain conditions and either just print them out, or kill either the connection or the query. So, for instance, to see all connections that have been idle for more than 2 minutes, we can use:

$ mysqlprocgrep --server=root:password@localhost --match-command=sleep --age=+2m
+------------------------+-----+-------+------------+-------+----------+-------+--------+-------+
| Connection             | Id  | User  | Host       | Db    | Command  | Time  | State  | Info  |
+------------------------+-----+-------+------------+-------+----------+-------+--------+-------+
| root:*@localhost:3306  | 39  | mats  | localhost  | None  | Sleep    | 248   |        | None  |
+------------------------+-----+-------+------------+-------+----------+-------+--------+-------+

In the example above, I would especially like you to note how the server connection information is provided. To provide information on what server to connect to and how, we have introduced a new syntax to represent the connection information which we call a connection specification:

user:password@host:port:socket

In the connection specification, the password, port, and socket are optional and can be excluded, which will make the default being used instead.

This is used instead of having separate switches (for example, –host and –user) that the server client programs are using. In addition to being easier to write, it also means that it is possible to provide multiple servers to command (where it makes sense, of course). You might be interested in knowing that both mysqlprocgrep and mysqlmetagrep accepts multiple servers.

If you now want to kill these idle connections, you can just add the –kill-connection option to the command, and the connection of all matching processes will be killed.

$ mysqlprocgrep --server=root:password@localhost \
> --match-command=sleep --age=+2m

In a similar way, if you have a long-running update from a special user (say, www-data), you can kill all the queries in one shot using the command:

$ mysqlprocgrep --server=root:password@localhost \
> --match-user=www-data --match-command=query    \
> --match-state=updating --age=+1m               \
> --kill-query

Example: finding objects using mysqlmetagrep

At times, you also find some odd reference to a column or index, you’re not quite sure, or you want to find out what objects are using a column named ‘db’. In those cases, mysqlmetagrep comes in handy.

The utility is used to find all objects that contain a field that matches the provided pattern. The pattern can be given either as a SQL simple pattern as defined by the SQL standard (this is what you usually use with LIKE), or using POSIX regular expressions (which is what you usually use with REGEXP in SQL). The default is to use the SQL simple pattern. So, to search for any objects having a column ‘host’, we can
use the command:

$ mysqlmetagrep --server=root:password@localhost --pattern=host --search=column
+------------------------+--------------+---------------+---------------------+-------------+----------+
| Connection             | Object Type  | Object Name   | Database            | Field Type  | Matches  |
+------------------------+--------------+---------------+---------------------+-------------+----------+
| root:*@localhost:3306  | TABLE        | PROCESSLIST   | information_schema  | COLUMN      | HOST     |
| root:*@localhost:3306  | TABLE        | columns_priv  | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | db            | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | host          | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | host          | mysql               | TABLE       | host     |
| root:*@localhost:3306  | TABLE        | procs_priv    | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | servers       | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | tables_priv   | mysql               | COLUMN      | Host     |
| root:*@localhost:3306  | TABLE        | user          | mysql               | COLUMN      | Host     |
+------------------------+--------------+---------------+---------------------+-------------+----------+

Since the SQL simple patterns are default, this require an exact match and you will only find objects with columns exactly named ‘host’. To find all column containing the word ‘host’, you have to add wildcards to the pattern:

$ mysqlmetagrep --server=root:password@localhost --pattern=%host% --search=column
+------------------------+--------------+---------------+---------------------+-------------+------------+
| Connection             | Object Type  | Object Name   | Database            | Field Type  | Matches    |
+------------------------+--------------+---------------+---------------------+-------------+------------+
| root:*@localhost:3306  | TABLE        | PROCESSLIST   | information_schema  | COLUMN      | HOST       |
| root:*@localhost:3306  | TABLE        | columns_priv  | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | db            | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | general_log   | mysql               | COLUMN      | user_host  |
| root:*@localhost:3306  | TABLE        | host          | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | procs_priv    | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | servers       | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | slow_log      | mysql               | COLUMN      | user_host  |
| root:*@localhost:3306  | TABLE        | tables_priv   | mysql               | COLUMN      | Host       |
| root:*@localhost:3306  | TABLE        | user          | mysql               | COLUMN      | Host       |
+------------------------+--------------+---------------+---------------------+-------------+------------+

Creating and configuring servers with ease

There are three utilites that I will just mention briefly, because they are not very complicated to use: mysqlserverclone, mysqlreplicate, and mysqluserclone.

To create a scratch servers using mysqlserverclone for testing something, it is as easy as:

$ mysqlserverclone --server=root:password@localhost \
> --new-data=/tmp/data
# WARNING: Root password for new instance has not been set.
# Cloning the MySQL server running on localhost.
# Creating new data directory...
# Configuring new instance...
# Locating mysql tools...
# Setting up empty database and mysql tables...
# Starting new instance of the server...
# Testing connection to new instance...
# Success!
#...done.

It will create a new server from the original, copy the existing databases, and and start the server. You can supply a new port using the –new-port, but if you do not do that, it will pick the default port 3307.

If you want to set up replication quickly and easily, you can do that using mysqlreplicate:

$ mysqlreplicate --master=root:password@localhost \
> --slave=root@localhost:3307 --rpl-user=repl_user:xyzzy
# master on localhost: ... connected.
# slave on localhost: ... connected.
# Checking for binary logging on master...
# Setting up replication...
# ...done.

When setting up replication, the mysqlreplicate does some basic checking to ensure that replication will work. It checks that there is a server ID assigned and also checks that binary logging is enabled. If something is not right, it will abort the setup and report error.

The last utility that is useful in setting servers up is mysqluserclone. The utility is used to create new users based on an existing one. So, to create a new user ‘chuck’ with password ‘xyzzy’ on localhost from an existing user ‘mats@localhost’,
you can use the command:

$ mysqluserclone --source=root:password@localhost \
> --destination=root:password@localhost \
> mats@localhost chuck:xyzzy@localhost
# Source on localhost: ... connected.
# Destination on localhost: ... connected.
# Cloning 1 users...
# Cloning mats@localhost to user chuck:xyzzy@localhost
# ...done.

Moving stuff around with ease

There are three utilities that can be used to move data around: mysqldbcopy, mysqldbexport, and mysqldbimport.

With mysqldbcopy, you can copy a database from one server to another, or several databases from one server to another. When copying a database, it not only copies the table definitions, but all associated objects such as triggers, events, routines, and also database-level grants.

With mysqldbexport you can export one or more databases into various formats, including (but not limited to) pure SQL, comma- and tab-separated values, and also a nice human-readable table.

With mysqldbimport you can import data in files into a database. In contast to using LOAD DATA INFILE, this will generate the INSERT statements to inject the data into the server.

The road ahead

The current set of utilities are just a small start, and we expect more utilities to be added over time and also improve on the existing utilities, so if you want to help, you can do that by:

We are very interested in feedback of any form—bug reports, suggestions for new utilities, suggestions for improving the existing utilities—so if you are a MySQL Expert DBA:

  • Let us know how to improve our utilities
  • Send us suggestions or ideas for new utilities
  • Write your own utilities
  • Contribute patches and/or new utilities

and if you are a Python programmer and/or developer:

  • Let us know how to be more Pythonic
  • Suggest improvements of the code
  • Build and/or contribute additional utilities on top of ones we provide

PlanetMySQL Voting: Vote UP / Vote DOWN

MySQL Workbench Plugin: Auto-Create Foreign Keys

Ноябрь 3rd, 2010

To automatically create Foreign Key relationships is a typical use case for developers working with the MyISAM storage engine. This has been a popular topic on the Blog and forums so we’re revisiting it here – with a new and improved plugin written in Python.

While the InnoDB storage engine supports foreign keys, MyISAM doesn’t, but developers often pick it for various reasons and leave the application to handle relationships itself. MySQL Workbench can be used to reverse engineer a database to a model to better visualize or maintain it. But since MyISAM doesn’t have foreign keys, databases that use it will be lacking a very important part of it’s structure in the diagrams. You can link the columns manually, using the relationship tool to link columns, but you can also automate that. Databases are usually created so that columns that represent relationships have names that follow some kind of convention or pattern. For example, a city table that is related to a country table, may have a column called country_id, used as the foreign key. The pattern there would be something like <table_name>_id. We can find all such pairs of columns between potential foreign keys and primary keys and create a foreign key for the tables.

There are two core routines needed by this implementation:

  • the first is to find candidate columns. That is, columns that could be foreign keys that reference primary keys of other tables, according to some pattern.
  • the second is the code to actually create the foreign keys from the possible columns found previously.

Look for Candidates

The following is the code to find candidate columns:

def get_fk_candidate_list(schema, fk_name_format, match_types):
    candidate_list = []
    possible_fks = {}
    # create the list of possible foreign keys out of the list of tables
    for table in schema.tables:
        if table.primaryKey and len(table.primaryKey.columns) == 1: # composite FKs not supported
            format_args = {'table':table.name, 'pk':table.primaryKey.columns[0].name}
            fkname = fk_name_format % format_args
            possible_fks[fkname] = table

    # go through all tables in schema again, this time to find columns that seem to be a fk
    for table in schema.tables:
        for column in table.columns:
            if possible_fks.has_key(column.name):
                ref_table = possible_fks[column.name]
                ref_column = ref_table.primaryKey.columns[0].referencedColumn
                if ref_column == column:
                    continue
                if match_types and ref_column.formattedType != column.formattedType:
                    continue

                candidate_list.append((table, column, ref_table, ref_column))
    return candidate_list

First, it will go through the list of all tables in the given schema and create a dictionary of possible foreign key column names, according to a format string provided by the user. The format string has the %(table)s and %(pk)s variables replaced with the table name and primary key column name.

With the dictionary of possible foreign key names at hand, it then goes through all columns of all tables looking for any column name that is in the dictionary. If a match is found, a tuple of table, column, referenced table and referenced column names are added to a list of candidates. If the match_types flag is True, it will also check if the column types match and discard anything that doesn’t.

Create Foreign Keys

With the list of candidate columns, we can create a foreign key object from the table column to its referenced column.

for table, column, ref_table, ref_column in candidates:
    fk = table.createForeignKey(ref_column.name+"_fk")
    fk.referencedTable = ref_table
    fk.columns.append(column)
    fk.referencedColumns.append(ref_column)

According to the db_Table documentation, table objects have a convenient createForeignKey method, which takes the foreign key name as an argument, and returns a new db_ForeignKey object added to the table. The foreign key is empty, so we set its referencedTable field and add the column/referenced column pair to the columns and referencedColumns lists, respectively.

Adding a GUI

Now, for a fancier version, we will create a dialog that takes the naming pattern from the user, shows the list of candidates and creates the foreign keys when a button is clicked:

This GUI version uses the internal mforms toolkit. It provides a native interface in any of the supported platforms. See the documentation for it here.

Here is the part of the code that creates the UI. You can use it as a template for your own plugin dialogs. Go to the end of the post for the full plugin code.

import mforms

class RelationshipCreator(mforms.Form):
  def __init__(self):
    mforms.Form.__init__(self, None, mforms.FormNone)

    self.set_title("Create Relationships for Tables")

    box = mforms.newBox(False)
    self.set_content(box)
    box.set_padding(12)
    box.set_spacing(12)

    label = mforms.newLabel(
"""This will automatically create foreign keys for tables that match
a certain column naming pattern, allowing you to visualize relationships
between MyISAM tables.

To use, fill the Column Pattern field with the naming convention used for
columns that are meant to be used as foreign keys. The %(table)s and %(pk)s
variable names will be substituted with the referenced table values.""")
    box.add(label, False, True)

    hbox = mforms.newBox(True)
    hbox.set_spacing(12)
    box.add(hbox, False, True)

    label = mforms.newLabel("Column Pattern:")
    hbox.add(label, False, True)
    self.pattern = mforms.newTextEntry()
    hbox.add(self.pattern, True, True)
    self.matchType = mforms.newCheckBox()
    self.matchType.set_text("Match column types")
    hbox.add(self.matchType, False, True)
    self.matchType.set_active(True)
    search = mforms.newButton()
    search.set_text("Preview Matches")
    search.add_clicked_callback(self.findMatches)
    hbox.add(search, False, True)

    self.pattern.set_value("%(table)s_id")

    self.candidateTree = mforms.newTreeView(mforms.TreeShowHeader)
    self.candidateTree.add_column(mforms.StringColumnType, "From Table", 100, False)
    self.candidateTree.add_column(mforms.StringColumnType, "Column", 100, False)
    self.candidateTree.add_column(mforms.StringColumnType, "Type", 100, False)
    self.candidateTree.add_column(mforms.StringColumnType, "To Table", 100, False)
    self.candidateTree.add_column(mforms.StringColumnType, "Column", 100, False)
    self.candidateTree.add_column(mforms.StringColumnType, "Type", 100, False)
    self.candidateTree.end_columns()
    box.add(self.candidateTree, True, True)

    hbox = mforms.newBox(True)
    hbox.set_spacing(12)
    self.matchCount = mforms.newLabel("")
    hbox.add(self.matchCount, False, True)
    self.cancelButton = mforms.newButton()
    self.cancelButton.set_text("Cancel")
    hbox.add_end(self.cancelButton, False, True)
    self.okButton = mforms.newButton()
    self.okButton.set_text("Create FKs")
    hbox.add_end(self.okButton, False, True)
    self.okButton.add_clicked_callback(self.createFKs)
    box.add(hbox, False, True)

    self.set_size(700, 600)

The dialog is implemented as a subclass of the mforms.Form class. That is the class for creating a window.

Line 5 calls the __init__ method of mforms.Form. Nothing fancy here, as we just want a plain normal window. Line 7 which follows, sets the title of the window.

Line 9, mforms.newBox(False) is used to create a box layouter that is “not horizontal” (ie, vertical). This is used to layout controls that are added to it from top to bottom, in a single column. Line 10 makes the window display this box as its first control. Anything else you want displayed in the window must be added to this box, either as a direct child or nested in other layouters children of this one.
Lines 11 and 12 set a padding around the box and a spacing between each item inside it, so we have a not so cluttered appearance in our dialog.

Line 14 creates a text label control with some rather lengthy description text, which is then added to the box we created above. The 2nd argument to the add method tells the layouter to not expand the added control. That is, the label will allocate as much space as it needs to show all its contents. If it was set to True, it would instead use all the space left in its container. The 3rd argument tells the layouter to fill the space allocated for it with the control. Since expand is False in this case, this won’t make much difference, but if it was True, it would toggle whether the label should have the same size as the space allocated for it or not. Note the difference between allocated space and actually used space.

Line 24 creates another box, this time a horizontal one, which is then added to the previously created vertical box. Anything added to this box will be laid out as a single row inside the first box. Anything added to the first box after this point, will be added below the row created by this box.

Lines 28 to 39 creates a label, a text field, a checkbox and a button, which are all laid in a row, using the horizontal box above. For the search button, we’re setting a callback which will be called when the user clicks it. The callback is just a method in the same class, called findMatches. It doesn’t take any argument.

A tree with 6 columns is then created from lines 43 to 50. The tree (which is just a plain list of rows) is set up by adding as many columns are desired, with their types, captions, default width and a flag telling whether the column is editable or not. After the columns are added, the end_columns() method must be called.

Finally, another row is added, starting from line 53. This row contains a Cancel and OK (Create FKs) buttons. Instead of add(), the add_end()method from Box is used, so that the buttons are laid out from right to left, instead of starting from the left to the right.

At last, the default size of the window is set.

This image shows rectangles around each of the boxes used to lay out the dialog.

The Whole Thing

To make this a plugin, there’s a few more bureaucratic lines of code that must be added. This code is described in our previous plugin tutorials and in the documentation.

The full plugin code contains the complete implementation. To install it, save it as relationship_create_grt.py and Install it from the Scripting -> Install Plugin/Module… menu item. After restarting Workbench, a new item called Create Relationships from Columns will appear in the Plugins -> Catalog menu.


PlanetMySQL Voting: Vote UP / Vote DOWN

Install, configure and run MySQL Cluster – demo video

Июль 23rd, 2010

There is a new video available: Demonstration of installing, configuring and running MySQL Cluster (LINUX) to accompany the MySQL Cluster Quick Start guides. The Flash video video lasts for about 7 minutes.

If you aren’t able to view Flash on your device then a (poorer quality) version is included here – watch the Flash version if you’re able to!


PlanetMySQL Voting: Vote UP / Vote DOWN

Quick start guides: MySQL cluster in 10 minutes

Июнь 25th, 2010
MySQL Cluster quick start guide Scared of MySQL Cluster?
Don't be. You may want to try the quick start guides that are available in the Cluster downloads page.
These guides are a step-by-step instructions set to create a simple cluster in one host.
Following the instructions, you will be able to shape up all the cluster components in 10 minutes or less. This will be far from production ready, of course, but it shows that cluster is not rocket science, and anyone can get started with it with a minimal time investment.
I tried the Linux instructions on my Mac, and it worked without need for any changes. Things may be different when you deploy a real set of servers on separate hosts, but it's a good start.
If I compare this guide with my first experience with MySQL Cluster in 2004, usability and stability have increased enormously.

PlanetMySQL Voting: Vote UP / Vote DOWN

Going to the O’Reilly MySQL Conference & Expo

Март 5th, 2010

As I've been doing the last couple of years, I will be going to the O'Reilly MySQL Conference & Expo. In addition to the tutorial and the replication sessions that I will be holding together with Lars, I will be holding a session about the binary log together with Chuck from the Backup team which the Replication team normally works very close with.

This year, O'Reilly also have a Friend of the Speaker discount of 25% that you can use when you register using the code mys10fsp.

The sessions that we are going to hold are listed below. Note that I am using Microformats, which will allow you to easily extract and add the events to your calendar using, for example, the Operator plugin for Firefox.

See you there!

Mysteries of the Binary Log
April 14th, 2010 10:50am - 11:50am Room: Ballroom F
New Replication Features
April 13th, 2010 2:00pm - 3:00pm Room: Ballroom A
Replication Tricks & Tips
April 14th, 2010 2:00pm - 3:00pm Room: Ballroom B
The Replication Tutorial
April 12th, 2010 8:30am - 12:00pm Room: Ballroom E

PlanetMySQL Voting: Vote UP / Vote DOWN

Free Tech Webinars

Октябрь 17th, 2009

You want to use or to know more about Sun technologies? We propose you free Webinars to improve your knowledge and  skills!

To register, just click on one of the following links:

  • Wednesday October 21st 2009: ZFS - Changing the Way You Look at Storage: ZFS is a new kind of file storage subsystem that provides simple administration, transactional semantics, end-to-end data integrity, and immense scalability. ZFS is not an incremental improvement to existing technology; it is a fundamentally new approach to data management. ZFS also combines, Disks, DRAM and Flash into one storage subsystem easily providing the best overall price performance for storage. Come learn about ZFS and its benefits. See a demo of how easy it is to use and administrate. Hear from a startup on their experience with ZFS.
  • October 14th 2009: Storage for your database: how databases can take advantage of ZFS, SSDs and the Open Storage line of products from Sun to increase data security, scalability, and reduce the price/performance ratio.

    Note: Everybody can join. Useful for ISVs and startups using a database in their application.

Note: Everybody can join. Especially useful for ISVs and startups.

Note : Everybody can join. Especially useful for ISVs and startups.


PlanetMySQL Voting: Vote UP / Vote DOWN

MySQL Workbench Administrator Plugin

Октябрь 7th, 2009

Recently we have released Workbench 5.2.4 Alpha. This version has some new features, and amongst them there is Workbench Administrator plugin or WBA plugin for short.

The plugin aims to ease the managing process of server instances. What we offer with WBA is a simple way to check status, configure and control one server instance. Some parts will resemble discontinued MySQL Administrator.

And here is a short summary of what we will have in WBA:

  • Start/Stop server
  • Edit server configuration (my.cnf)
  • Manage user accounts
  • Monitor user connections
  • Status/Server variables browsing
  • Log browsing
  • Dump/Restore

In this alpha we have implemented a subset, which targets local usage only. Remote management and administration is upcoming. The subset includes:

  • Add new Server Profiles
  • Start/Stop the Server
  • Edit Server Configuration (my.cnf)
  • Monitor user connections
  • Status/Server variables browsing

To launch the plugin you need to run Workbench 5.2.4, register a server instance by double-clicking the Manage Icon. Once the server instance is registered you can double click the icon of the server instance. But for the moment let’s dive into what is important to specify at the server instance creation stage.

Our target is ‘System Profile’ tab of ‘Manage Server Instances’ form. Mostly, the whole process should be simple selecting the right profile. Nevertheless, for now (I hope you still remember it is an alpha release), one of the vitally important things is to check location of ini or cnf file. Also you may check commands used to start, stop and query server status. For example OS X profile has that line to check for status: ps -cxa | grep mysqld.

All the commands specified in these entries are run as a sub-processes and sometimes they may require super-user privileges, for that purpose there is ‘use sudo’ checkbox. Normally, command run has exit code which WBA checks for to determine success of failure of the command.

When adding a new Server Profile you also need to select a Connection to the server (You should create that connection in the Connection Management dialog first). That will allow you to browse the Connections and Server Variables in the WBA. It will also be used to update the Server Status periodically every second and show the current state (that is in next alpha).

The way to change the my.cnf/my.ini config file is pretty straightforward. First, if you want a value to be written to the config file, you have to enable the checkbox left to each option. After all changes have been made, you can either press Apply or Discard button. Apply will display a Dialog which shows several things: what has changed, resulting file, commands which are used to save file. If changes are correct, press Apply on the form. That is it.

Stay tuned for the updates on WBA topic.


PlanetMySQL Voting: Vote UP / Vote DOWN

Backup MySQL in a Second with ZFS

Сентябрь 29th, 2009

MySQL backup soon becomes an important matter when the database is used in production. The pain-point comes from the fact that while backuping the database is not available to respond to client requests anymore. With mysqldump - the standard tool for performing MySQL backups - and a large database the operation can go over many tenth of minutes if not hours. If I am running my business on line this is simply not acceptable.

The classical approach to workaround this problem is to take advantage of MySQL replication. I set up a master/slave configuration where the slave acts as copy of the master. Then, when needed, I run mysqldump on the slave without any service interruption on the master.

But ZFS snapshosts bring a new straightforward approach that avoids the pain and the complexity of a master/slave replication.

Snapshots are a key feature of ZFS that allows me to save a copy of any ZFS file system in less than a second. Yesterday, Sept 27th I first created a myDB ZFS filesystem for my database, and since I decided to backup my database everyday I also created a first snapshot. I am using InnoDB, so I made sure that both the data and the logs are located in the myDB filesystem. Today, Sept 28th, I created a second snapshot. Here are the commands:

Yesterday, September 27th


# zfs create pool/myDB
# zfs snapshot pool/myDB@Sept27.2009

Today, September 28th


# zfs snapshot pool/myDB@Sept28.2009

Note that as long as the dataset does not change, the snapshot does not use any disk space, so since there was no change to the database when I created the first snapshot zfs list reporst me a null USED space :


# zfs list -t snapshot
NAME                                     USED AVAIL REFER MOUNTPOINT
pool/myDB@Sept27.2009   0         -          667M   

The commands are simple, but what about the performance? If I run the commands just as is, the filesystem that I save takes 667M on disk. On my labtop I have much more data in my home directory. Let's see how long it takes me to snapshot this data.


# zfs list rpool/export/home/tmanfe
NAME                                      USED  AVAIL  REFER  MOUNTPOINT
rpool/export/home/tmanfe   47.8G   22.5G     28.1G     /export/home/tmanfe

# time  zfs snapshot rpool/export/home/tmanfe@28.2009
real    0m0.370s
user   0m0.004s
sys     0m0.009s


I am able to snapshot 47.9GBytes of data in 0.37seconds. Good enough. As long as I can stay bellow a second, this will certainly go unnoticed by the users. By the way, should my dataset increase, the snapshot time will stay the same.

Now, what do I need to do with MySQL?

For my data to be properly and consistently saved, I need to make sure that it gets written to disk. To do this, MySQL provides me with the command FLUSH and its TABLES WITH READ LOCK option. About this option the documentation says: "Closes all open tables and locks all tables for all databases with a read lock until you explicitly release the lock by executing UNLOCK TABLES. This is very convenient way to get backups if you have a file system such as Veritas that can take snapshots in time". Note that the documentation should be modified to add ZFS as another filesystem that supports snapshots.

Since I am using InnoDB I also need to turn autocommit off before running the FLUSH command otherwise every MySQL statement - such as FLUSH TABLES WITH READ LOCK - is wrapped into a transaction and at the end of each transaction all the table locks are released. In other words, my attempt to lock tables would be self-canceling, would have no effect. No such thing is required with MyISAM.

Then, I create the ZFS snapshot and I release the tables with the command UNLOCK TABLES. I am done with MySQL!

The snapshot I created is located on the same disks and server than my original data. To put a real backup system in place I need to transfer the snapshot to another backup server or storage system. Once again ZFS provides me with all I need. The zfs send command enables me to send a snapshot somewhere else. The only prerequisite is that ZFS must be available on my  backup server in order to take advantage of the snapshot that it receives.

Here is the exact syntax:


# zfs send -Ri pool/myDB@Sept27.2009 pool/myDB@Sept28.2009 | ssh backupHost “zfs receive -Fd pool”


With the -i option, only the difference between my two snapshots is sent to a system named backupHost. This option enables me to do incremental backups. Ahead of incremental backups I need to send a first complete snapshot to the backup host. I did it yesterday, when creating my very first  snapshot:


# zfs send -R pool/myDB@Sept27.2009 | ssh backupHost “zfs receive -Fd pool”


Note that the stream generated by zfs send replicates the filesystem, not the snapshot.

The stream is then funneled into an ssh command that connects to the backup host. Once connected, the zfs receive command is executed that takes the content of the stream - i.e. the filesytem - and copies it into a zfs pool that is local to the backup host.

I am done.


PlanetMySQL Voting: Vote UP / Vote DOWN