Today we're releasing MySQL Connector/Python 0.1.0-devel. This is the first in a serie of development snapshots aimed to get more people trying it out and reporting problems. This is not a production-ready release, but it should work on all Unices and Windows which has Python 2.4 or later installed. (No, no Py3K, yet!)
You can download it from Launchpad: there is a .tar.gz and .zip
There will be documentation and tutorial, but installation is as easy as pie (pun intended):
shell> tar xzf mysql-connector-python-0.1.0-devel.tar.gz
shell> cd mysql-connector-python-0.1.0-devel
shell> python ./setup.py install
If you want to run the unittests, you'll need a MySQL server running locally.
A week ago we found a workaround for a bug in MySQL Cluster making it impossible to run a management node on MacOS X. Until the bug is fixed, you should use the --nodaemon option for the ndb_mgmd executable. Both MySQL Cluster v6.3 and v7.0 are affected.
Currently, I'm starting the management node like this:
(
cd /opt/mysql/mysql ;
./libexec/ndb_mgmd -f /opt/mysql/config.ini \
--nodaemon 2>/dev/null 1>&2 </dev/null &
)
Obviously, you'll want to change the paths.
Eventually, the bug will get fixed, but until then you got no excuse to not try MySQL Cluster on Mac!
What you do when you're fed up with a script? Right, you write your own.
You'll have to excuse me for the long shell script you'll find here below, but I'm not going to bother putting it on some download website.
It's a shell script which starts and stops the MySQL server. Indeed, a replacement for the init.d script found in the MySQL distributions. I'm using it personally on my Macs and it's not supported in any way.
But why? Well, I'm playing with MySQL Workbench, Server Administration. The MySQL init.d script didn't work right away (oh, various reasons for that), so I used mine. So I figured it might be useful for others and it's not complicated or shocking-new-stuff.
If you want to use it, you'll have to edit the 2 variables at the top. It's only going to work on MacOS X.
#!/bin/bash
# Author: Geert Vanderkelen <geert@kemuri.org>
BASEDIR="/opt/mysql/mysql"
CNF="/opt/mysql/my51.cnf"
MODE="$1"
_RETURN="" # for returning from functions
pidof() {
local CMD=$1
local PID=`ps cax -o "pid,command" | awk -v cmd="$CMD" '{ if (\$2 == cmd) printf("%s",\$1) }'`
if [ "x$PID" == "x" ]; then
_RETURN=""
return 1
else
_RETURN=$PID
return 0
fi
}
checkprocess() {
local CMD=$1
_RETURN=""
pidof $CMD
if [ $? -eq 0 ];
then
local PID=${_RETURN}
kill -n 0 $PID 2>/dev/null 1>&2
if [ $? -ne 0 ]; then
return 2
fi
_RETURN=$PID
return 0
fi
return 1
}
waituntildown() {
local CMD=$1
pidof $CMD
while [ $? -eq 0 ]; do
echo -n '.'
sleep 1
pidof $CMD
done
}
exec_mysqld_safe() {
(
cd $BASEDIR
./bin/mysqld_safe --defaults-file=$CNF 2>/dev/null 1>&2 </dev/null &
)
}
status() {
checkprocess mysqld
RET=$?
if [ $RET -ne 0 ]; then
if [ $RET -eq 1 ]; then
echo "MySQL is not running."
elif [ $RET -eq 2 ]; then
echo "You have no permission to stop MySQL."
fi
return 1
fi
return 0
}
start() {
checkprocess mysqld
if [ $? -eq 0 ]; then
echo "MySQL is running."
exit 1
fi
echo -n "Starting MySQL.. "
exec_mysqld_safe
sleep 2
checkprocess mysqld
if [ $? -ne 0 ]; then
echo " Failed!"
exit 1
fi
echo " OK"
}
stop() {
status
RET=$?
if [ $RET -ne 0 ]; then
exit 1
fi
PID=${_RETURN}
echo -n "Stopping MySQL.. "
kill $PID 2>/dev/null 1>&2
if [ $? -eq 0 ]; then
waituntildown mysqld
echo " OK"
else
echo " Failed!"
fi
}
case "$MODE" in
"start")
start
;;
"stop")
stop
;;
"restart")
stop
start
;;
"status")
status
if [ $? -eq 0 ]; then
echo "MySQL is running."
exit 0
else
exit 1
fi
;;
"getpid")
pidof mysqld
if [ $? -eq 0 ]; then
echo ${_RETURN}
fi
;;
*)
echo "Usage: $0 {start|stop|restart|status|getpid}"
exit 1
;;
esac
Work says that we need to store sensitive data like email and customer files on some encrypted media. This is a good thing. My laptop has my home directory secured, but I don't want to encrypt everything on my desktop. The solution to this is to create an encrypted Disk Image (using Disk Utility) and make Mail.app store my email there. This all works great!
The problem surfaced this week when I decided it would be good to shutdown my desktop to save energy (which I usually did, but I got sloppy). What happened? When Mac OS X shuts down, and there is still some application doing something with your opened Disk Image, it will not remove the mount-point, e.g. in my case /Volumes/FileVaultBlack. Later, if you open it again, Mac OS will create the directory /Volumes/FileVaultBlack 1 and use that as mount-point. The issue here is that I configured the AccountPath in Mail.app to a location in /Volumes/FileVaultBlock.. In mortals speech: "Email is broken".
The solution is to mount the Disk Image when logging in using a predefined mounting point. This involves making a directory and creating an AppleScript application. So lets get busy!
First, eject the Disk Image using the Finder application. It will complain when applications still need it, so you have to make sure that nothing is accessing it.
Create the mountpoint. The idea is to create a directory in /Volumes/ (it doesn't really matter where you do it, but I like to keep them in one place). I suggest opening Terminal for this and do the following:
shell> mkdir /Volumes/FileVaultBlack
You want to name it differently. I'm using the name of the Disk Image, just like MacOS would do when you double click the .dmg-file.
Open AppleScript Editor and save the following script into a file called, for example, FileVaultBlack_mountatlogin.
do shell script "hdiutil attach /Users/geert/FileVaultBlack.dmg -mountpoint /Volumes/FileVaultBlack"
The above script will execute the hdiutil command-line utility telling it to mount the given Disk Image (.dmg-file) on the give mount-point (the one we created earlier).
Test this script by pushing the Run-button in the AppleScript Editor and see whether your Disk Image is visible in Finder. If not, check the locations of both the Disk Image and the mount-point you gave in the script.
When you saved it, save it again as an application. Still within the AppleScript Editor do the following:
- Choose Save As from the File menu
- Save As: save it using slighly different name, for example MountFileVaultBlack
- File Format: Application
- You don't have to check Run Only
We save it 2 times, once as a script, once as an application. This way, you can easily edit the script later, and save it again as an application. (I'm using different names because it's less confusing when writing this post.)
Lets now add it to our Login Items:
- Open System Preferences and go to Accounts
- Make sure you choose My Account, i.e. your account, and go to Login Items
- Add an item to the list, clicking the +-sign
- Locate the application you created above, in our exampled named MountFileVaultBlack, and press Add.
- Check also the Hide option next to the new item.
That should be it. Log out and in and check if the Disk Image is mounting. There should be an icon happily jumping in the Dock while the mounting is on-going. Open Finder and see if your files are accessible.
Here is a quick way to compile a simple MGM API application. The example will get the state of all nodes in MySQL Cluster and print whether they are connected or not.
All this without a Makefile, we just want to have some simple example on Linux to see how it works. It's basic, maybe, but sometimes useful to just have a peek.
Requirements! We assume that:
- you installed MySQL Cluster 6.3 or higher, preferably under /usr/local/mysql,
- your cluster is up and shiny,
- and ndb_mgmd runs on the same machine you are compiling the MGM API test application on.
The code, save it in a file called mgmapi_test.cc (from the MySQL manual):
#include <stdlib.h>
#include <mgmapi/mgmapi.h>
int main()
{
NdbMgmHandle handle = ndb_mgm_create_handle();
ndb_mgm_set_connectstring(handle,"localhost");
ndb_mgm_connect(handle,0,0,0);
struct ndb_mgm_cluster_state *state = ndb_mgm_get_status(handle);
for(int i=0; i < state->no_of_nodes; i++)
{
struct ndb_mgm_node_state *node_state= &state->node_states[i];
printf("node with ID=%d ", node_state->node_id);
if(node_state->version != 0)
printf("connected\n");
else
printf("not connected\n");
}
free((void*)state);
ndb_mgm_destroy_handle(&handle);
}
Lets compile it! Note that it goes all on one line, but you could also paste the following lines in a shell script:
(
MYBASE="/usr/local/mysql";
PATH="$MYBASE/bin:$PATH";
g++ `mysql_config --libs` `mysql_config --cflags` -lndbclient \
-I$MYBASE/include/storage/ndb \
-o mgmapi_test mgmapi_test.cc
)
No errors? Lets run it! Setting LD_LIBRARY_PATH doesn't hurt:
(
export LD_LIBRARY_PATH="/usr/local/mysql/lib";
./mgmapi_test
)
The result should be something like this:
node with ID=1 connected
node with ID=2 connected
node with ID=3 connected
node with ID=4 connected
node with ID=10 connected
node with ID=11 not connected
node with ID=12 not connected
node with ID=13 not connected
..
FAQ: Wouldn't it be better to have a Makefile? Absolutely. Will there be problems doing it above? Sure, but the error message should help; start by checking if the locations are OK.
You can define a view in MySQL as follows:
CREATE VIEW v AS SELECT
'MySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQL';
The above long string might give trouble reading, but 'MySQLMy..' is 70 characters long. It will work fine, but check out how MySQL stores it (output of SHOW CREATE VIEW):
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`
SQL SECURITY DEFINER VIEW `v` AS select
'MySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQL'
AS `MySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQL`
This is where the trouble starts. If you backup your schema using mysqldump, it will get the above definition, but when you restore it, you'll get the following error:
ERROR 1166 (42000) at line 43: Incorrect column name
'MySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQL'
Why? Quoting the MySQL Manual:
"As of MySQL 5.1.23, aliases for column names in the SELECT statement are checked against the maximum column length of 64 characters (not the maximum alias length of 256 characters)."
Solutions, and general good practice:
- Use columns when defining the view: CREATE VIEW v (MySQLString) AS SELECT 'MySQLMy..
- or use an alias: CREATE VIEW v AS SELECT 'MySQLMy..' AS `MySQLString`
Both will result in the following being stored:
CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`
SQL SECURITY DEFINER VIEW `v` AS select
'MySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQLMySQL'
AS `MySQLString`
In my honest opinion, there should be a warning stating that the resulting alias is too long. This was discussed in bug #36287.
Note: If you got the above ERROR 1166 with your views, it means you never tested your backups! HA! Got ya!
I'm currently planning a first 'alpha' release of MySQL Connector/Python, but I'm now doubting whether the naming and installation of the module is actually good.
Currently, the module lives, in site-packages/mysql/connector/, or import mysql.connector. Since this is an official MySQL, sorry, Sun Microsystems, project, I thought that the 'parent' module mysql would be good enough.
But is it? Would it break your modules with the same name?
The idea was to make more tools for Python and have them all under the mysql module, but maybe we need a smarter name for this? Maybe sunmysql/connector?
Comments are welcome! You can also email me directly (if you can figure out the cryptic anti-spam): geert_dot_vanderkelen_APETAIL_sun_dot_com.
So, I'm in Poland right now. I check my Google account: it's in Polish. No way to set it in English, though my browser preferences are set so. You would have thought smart people work at Google, right? No, the broken way to set language: based on IP address. What's even more idiotic is the fact that you can't actually change to English (or your favorite language). (see screenshot)
Google, I like your services, but this one totally disappointed me. With all the smart people working there, not one figured out that people actually travel?
To all other websites that just switch language based on IP Address: my thumbs down! Show at least a language option! (Lots do BTW)
This is not about email, but the mail dropped into the mailbox at home.. Take the none important letters and stupid magazines and tell the folks you don't want to get anything at home anymore. At least in Germany, it worked well today telling them through email, phone call and going in person.
Tomorrow I should do a few more to make sure no junk mail is littered in my box. Also, there are still idio^H^H^H^Hpeople out there that can't read the stickers saying 'No spam please'.
MySQL Cluster 6.3.28 and 7.0.9 introduce the MySQL server option --ndb-wait-setup. This makes sure that clients can not connect the SQL Node when no Data Nodes are available within, by default, 15 seconds. When the timeout is reached, and no Data Nodes are available, the NDB storage engine will be marked as unavailable.
The following will appear in the MySQL server error log when --ndb-wait-setup=30 has been set:
[Note] NDB: NodeID is 10, management server 'ndbsup-priv-1:1406'
[Note] NDB[0]: NodeID: 10, no storage nodes connected (timed out)
[Note] Starting Cluster Binlog Thread
[Note] Event Scheduler: Loaded 0 events
[Note] NDB Binlog: Ndb tables initially read only.
.. 30 seconds later..
[Warning] NDB : Tables not available after 30 seconds.
Consider increasing --ndb-wait-setup value
[Note] /data1/mysql/5.1.39_6.3.28/libexec/mysqld: ready for connections.
Use case: when doing an installation and you start Data and SQL Nodes quickly after each other. Normally, services which connect to a MySQL server (which is connect to a MySQL Cluster) will have failures because NDB tables are not yet available. With --ndb-wait-setup option set, they will not even be able to connect. It could help in some automated install scenarios where you want to make sure clients can't do anything until Data Nodes are available.
Stay tuned for the binaries due first half of November (2009). Source is already available for MySQL Cluster 7.0.9 and 6.3.28.
