<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>2nd floor &#187; Databases</title>
	<atom:link href="http://lmorgado.com/blog/category/databases/feed/" rel="self" type="application/rss+xml" />
	<link>http://lmorgado.com/blog</link>
	<description>bits and pieces of geeky fun</description>
	<lastBuildDate>Tue, 17 Jan 2012 01:22:53 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Lua and mysql-proxy: how to send a query to an email</title>
		<link>http://lmorgado.com/blog/2011/03/11/lua-and-mysql-proxy-how-to-send-a-query-to-an-email/</link>
		<comments>http://lmorgado.com/blog/2011/03/11/lua-and-mysql-proxy-how-to-send-a-query-to-an-email/#comments</comments>
		<pubDate>Fri, 11 Mar 2011 16:17:53 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[lua]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql-proxy]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=298</guid>
		<description><![CDATA[I recently got an inquiry on how to receive an email every time a query was executed via the MySQL proxy. This is very simple and you can achieve it by simply piping the query to the *nix mail command. Here is the sample code (in a file caled send_mail.lua): 1 2 3 4 5 [...]]]></description>
			<content:encoded><![CDATA[<p>I recently got an inquiry on how to receive an email every time a query was executed via the MySQL proxy. This is very simple and you can achieve it by simply piping the query to the *nix mail command. Here is the sample code (in a file caled send_mail.lua):</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
</pre></td><td class="code"><pre class="language" style="font-family:monospace;">function read_query(packet)
  if string.byte(packet) == proxy.COM_QUERY then
    print(&quot;Hello world! Seen the query: &quot; .. string.sub(packet, 2))
    print(&quot;Sending query to email:&quot;)
    os.execute(&quot;echo &quot; .. string.sub(packet, 2) .. &quot;| mail -s'Lua test' your.email.here@example.com &quot;)
  end
end</pre></td></tr></table></div>

<p>To execute this, install proxy as per the instructions in the <a title="How to install mysql proxy" href="http://dev.mysql.com/doc/refman/5.5/en/mysql-proxy-install.html" target="_blank">manual</a>. Then simply run the proxy and point it at your script:<br />
<code><br />
shell&gt; bin/mysql-proxy --proxy-lua-script=send_email.lua &amp;<br />
</code><br />
Finally, connect to the proxy and issue a query:<br />
<code><br />
shell> mysql -h127.0.0.1 --port=4040<br />
...<br />
mysql> SELECT "Test 1";<br />
Hello world! Seen the query: SELECT "Test 1"<br />
Sending query to email:<br />
+--------+<br />
| Test 1 |<br />
+--------+<br />
| Test 1 |<br />
+--------+<br />
1 row in set (0.00 sec)<br />
</code></p>
<p>You&#8217;ll shorty receive email with the query above. Happy Lua scripting. </p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2011/03/11/lua-and-mysql-proxy-how-to-send-a-query-to-an-email/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Configuring MySQL Enterprise Monitor to authenticate from LDAP</title>
		<link>http://lmorgado.com/blog/2010/10/11/configuring-mysql-enterprise-monitor-to-authenticate-from-ldap/</link>
		<comments>http://lmorgado.com/blog/2010/10/11/configuring-mysql-enterprise-monitor-to-authenticate-from-ldap/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 21:00:26 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL Enterprise Monitor]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=221</guid>
		<description><![CDATA[In the last post, we saw how to create a test OpenLDAP server, populate it and secure it with SSL certificates. Now we are going to have a look at how to configure MySQL Enterprise Manager (MEM) to authenticate against LDAP. We will be examining a few different kinds of setup methods. 1. Using LDAP [...]]]></description>
			<content:encoded><![CDATA[<p>In the last <a href="http://lmorgado.com/blog/2010/10/11/setting-up-openldap-for-mysql-enterprise-monitor/">post</a>, we saw how to create a test OpenLDAP server, populate it and secure it with SSL certificates. Now we are going to have a look at how to configure MySQL Enterprise Manager (MEM) to authenticate against LDAP. We will be examining a few different kinds of setup methods.</p>
<h2>1. Using LDAP to fetch just the user password</h2>
<p>The simplest form is to configure a user with MEM and set it to the LDAP type. The user&#8217;s role is setup in MEM during user creation time and is not fetched from LDAP. Below you can see the user definition page:</p>
<div id="attachment_222" class="wp-caption alignnone" style="width: 749px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-passwordonly.png"><img class="size-full wp-image-222 " title="How to  create a LDAP user in MEM - password only" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-passwordonly.png" alt="How to create a LDAP user in MEM - password only" width="739" height="306" /></a><p class="wp-caption-text">How to create a LDAP user in MEM - password only</p></div>
<p>The username is <strong>user1</strong> as specified in MEM, but where do we get the password from? We need to tell MEM how to find this user. Here is a sample user as defined by the <a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap.ldif_.txt">LDIF file</a> used in my previous post:</p>
<pre># user1, People, example.com
dn: uid=user1,ou=People,dc=example,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
cn: Aaren Atp
sn: Atp
description: This is the description for Aaren Atp.
employeeNumber: 1
givenName: Aaren
homePhone: +1 280 375 4325
initials: ALA
l: New Haven
mail: user.1@maildomain.net
mobile: +1 680 734 6300
ou: admin
pager: +1 850 883 8888
postalAddress: Aaren Atp$70110 Fourth Street$New Haven, OH  93694
postalCode: 936942
st: OH
street: 70110 Fourth Street
telephoneNumber: +1 390 103 6917
uid: user1
userPassword:: e1NTSEF9Z0tsZjU4cm50Wit4b045N0U4cWlldVJQK1RMOVAzTGw=</pre>
<p>Now tell MEM to look for the <em>uid</em> by navigating to Settings &gt; Global Settings &gt; LDAP Authentication:</p>
<div id="attachment_225" class="wp-caption alignnone" style="width: 712px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-settings-1.png"><img class="size-full wp-image-225 " title="MEM settings for LDAP password lookup only" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-settings-1.png" alt="MEM settings for LDAP password lookup only" width="702" height="580" /></a><p class="wp-caption-text">MEM settings for LDAP password lookup only</p></div>
<p>The password is specified in the <em>userPassword</em> attribute and uses standard LDAP supported formats. Technically what MEM does is an LDAP simple bind operation (Authentication Mode = Bind as User) with the given username/password and then attempts to search for the given user using the DN pattern.  If the binding and search succeeds, we assume the  password is correct. With this in place, you can now login with <strong>user1</strong> without having to specify the password in MEM.</p>
<h2>2. Adding MEM Roles from LDAP</h2>
<p>If we want to fetch the user&#8217;s role from LDAP in addition to the  password, we need to enable the <em>Map LDAP Roles to Application Roles</em> check box in the LDAP settings page. We&#8217;ll see the two ways of doing this shortly.</p>
<p>The good thing about enabling role mapping is that manual user creation in the Web dashboard is no longer required. If the user does not already exist within MEM, it will be &#8220;copied&#8221; from LDAP to MEM when that user first logs in. The lookup order is Built-in users first, then LDAP users. If you want user authentication to be exclusively done against LDAP then make LDAP authoritative by ticking the check box:</p>
<div id="attachment_250" class="wp-caption alignnone" style="width: 582px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-ldap.png"><img class="size-full wp-image-250" title="MEM authoritative LDAP authentication" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-ldap.png" alt="MEM authoritative LDAP authentication" width="572" height="631" /></a><p class="wp-caption-text">MEM authoritative LDAP authentication</p></div>
<p><span style="color: #ff0000;"><strong>WARNING:</strong></span> Enabling this prevents Built-in users from being authenticated. Make sure that you test with non authoritative authentication first and make sure role mapping is working. Also, ensure that you have a valid LDAP user who has <strong>admin</strong> privileges or risk locking yourself out.</p>
<p>Below is an example of how my test user table looked before logging in with <strong>user1</strong>:</p>
<div id="attachment_253" class="wp-caption alignnone" style="width: 459px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-users-b4.png"><img class="size-full wp-image-253" title="User table before LDAP login" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-users-b4.png" alt="User table before LDAP login" width="449" height="283" /></a><p class="wp-caption-text">User table before LDAP login</p></div>
<p>And this is how it looks after a successful login:</p>
<div id="attachment_254" class="wp-caption alignnone" style="width: 487px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-users-after.png"><img class="size-full wp-image-254" title="User table after LDAP login" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-auth-users-after.png" alt="User table after LDAP login" width="477" height="290" /></a><p class="wp-caption-text">User table after LDAP login</p></div>
<p>Notice how the LDAP <strong>user1</strong> entry was created automatically in the MEM user table with values from the LDAP directory.</p>
<h2>2.2.1 MEM roles in a LDAP user&#8217;s attribute</h2>
<p>The first way of achieving role mapping is to simply have an attribute in the user&#8217;s entry, whose attribute value will be the role. In our example, we use the <em>ou</em> attribute. The relevant attributes for our sample users are:</p>
<pre>uid: user1
ou: admin
....
uid: user2
ou: dba</pre>
<p>The relevant settings in MEM are:</p>
<div id="attachment_231" class="wp-caption alignnone" style="width: 479px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-settings-2.png"><img class="size-full wp-image-231  " title="MEM settings for LDAP role mapping with user attributes" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-settings-2.png" alt="MEM settings for LDAP role mapping with user attributes" width="469" height="596" /></a><p class="wp-caption-text">MEM settings for LDAP role mapping with user attributes</p></div>
<p>Now when you login with <strong>user2</strong> for example, its role will be fetched from LDAP. We can verify this in the User Preferences section as shown by the screenshot below:</p>
<div id="attachment_238" class="wp-caption alignnone" style="width: 533px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-user-role-map.png"><img class="size-full wp-image-238 " title="A user that has authenticated via  LDAP with role mapping" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-user-role-map.png" alt="A user that has authenticated via LDAP with role mapping" width="523" height="430" /></a><p class="wp-caption-text">A user that has authenticated via LDAP with role  mapping</p></div>
<p>If we try <strong>user1</strong>, then we will get an <strong>admin</strong> (manager) role.</p>
<p>Note that some versions have a <a href="http://bugs.mysql.com/bug.php?id=55450">bug</a> that prevents this setup from working. Check if you are affected.</p>
<h2>2.2.2 MEM roles specified by a LDAP group</h2>
<p>There is another way to specify a user&#8217;s role. Instead of each user having an attribute representing the role, a roles group is created, which enumerates the users that are members of that role. In our example, this is represented in the <a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap.ldif_.txt">LDIF file</a> as:</p>
<pre>dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups

dn: cn=admin,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
cn: admin
uniqueMember: uid=user1,ou=People,dc=example,dc=com

dn: cn=dba,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
cn: dba
uniqueMember: uid=user2,ou=People,dc=example,dc=com</pre>
<p>So again, we need to tell MEM how to do role lookups from the LDAP directory.  This is how the LDAP settings in MEM would look like for our particular case:</p>
<div id="attachment_248" class="wp-caption alignnone" style="width: 456px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-roles-group.png"><img class="size-full wp-image-248" title="MEM settings for LDAP role mapping in groups" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-roles-group.png" alt="MEM settings for LDAP role mapping in groups" width="446" height="588" /></a><p class="wp-caption-text">MEM settings for LDAP role mapping in groups</p></div>
<p>Note, that due this <a href="http://bugs.mysql.com/bug.php?id=54806">bug</a>, you might not get this particular setup to work.</p>
<h2>2.3 Configuring LDAP lookups to use SSL and STARTTLS</h2>
<p>Once plain text authentication is working, you can choose to secure communications between MEM and the LDAP server with either STARTTLS or SSL. Obviously the LDAP server must support it. Note that SSL (ldaps) is deprecated in the latest LDAP v3 and STARTTLS is prefered. MEM supports both types. To use STARTTLS, simply select it in the menu as follows:</p>
<div id="attachment_261" class="wp-caption alignnone" style="width: 444px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-starttls.png"><img class="size-full wp-image-261" title="MEM with STARTTLS LDAP authentication" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-starttls.png" alt="MEM with STARTTLS LDAP authentication" width="434" height="227" /></a><p class="wp-caption-text">MEM with STARTTLS LDAP authentication</p></div>
<p>There is no need to change the default port. Using SSL (ldaps) however, implies using the ldaps port, which by default is 636, and setting MEM to use SSL(ldaps) :</p>
<div id="attachment_262" class="wp-caption alignnone" style="width: 519px"><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-ldaps.png"><img class="size-full wp-image-262" title="MEM with SSL (ldaps) LDAP authentication" src="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap-ldaps.png" alt="MEM with SSL (ldaps) LDAP authentication" width="509" height="258" /></a><p class="wp-caption-text">MEM with SSL (ldaps) LDAP authentication</p></div>
<p>One thing to note is that the (Primary) Server Hostname should match the SSL certificate of the LDAP server.</p>
<p>If you are using self signed certificates that were not issued by a commercial SSL company, MEM will not have the root CA (Certificate Authority) in it&#8217;s repository. You should see a message in the $INSTALL_DIR/monitor/apache-tomcat/logs/catalina.out logfile:</p>
<pre>javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target</pre>
<p>To fix this, you will need to import the your root CA certificate that was used to generate the LDAP server&#8217;s certificate. This can be achieve with the Java Keytool utility as follows:</p>
<pre>shell&gt; cd  /opt/mysql/enterprise/monitor/java</pre>
<pre>shell&gt; bin/keytool -import -trustcacerts -alias ldapssl \
       -file /etc/openldap/ssl/ca-cert.pem -keystore lib/security/cacerts</pre>
<p>This needs to be run under MEM&#8217;s Java installation directory. Unless you have previously modified it, the default password is <strong>changeit</strong> . We saw how to create a CA certificate (ca-cert.pem) in the previous <a href="http://lmorgado.com/blog/2010/10/11/setting-up-openldap-for-mysql-enterprise-monitor/">post</a>. Finally, restart the MEM monitor service.</p>
<p>In case you have problems importing your root CA certificate, make sure it is correctly format and acceptable by the Java keytool utility:</p>
<p>&#8220;<strong>keytool</strong> can import X.509 v1, v2, and v3 certificates, and PKCS#7 formatted certificate chains consisting of certificates of that type. The data to be imported must be provided either in binary encoding format, or in printable encoding format (also known as Base64 encoding) as defined by the <a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/tools/windows/keytool.html#EncodeCertificate"> Internet RFC 1421 standard</a>. In the latter case, the encoding must be bounded at the beginning by a string that starts with &#8216;&#8212;&#8211;BEGIN&#8217;, and bounded at the end by a string that starts with &#8216;&#8212;&#8211;END&#8217;.&#8221;</p>
<p><a href="http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/tools/windows/keytool.html">http://download.oracle.com/docs/cd/E17409_01/javase/6/docs/technotes/tools/windows/keytool.html</a></p>
<p>To troubleshoot, the best place is to look at the catalina.out logfile. If you need extra debugging information, you can start MEM&#8217;s JVM as follows:</p>
<pre>JAVA_OPTS="$JAVA_OPTS -Djavax.net.debug=ALL"</pre>
<p>In the current version (2.2.1.1721) this should be added at <span style="text-decoration: line-through;">around line 180 of $INSTALL_DIR/monitor/apache-tomcat/bin/catalina.sh</span>. Note that catalina.sh will get overwritten when you next upgrade so if you want JAVA_OPTS changes to be persistent, then use setenv.sh (or setenv.bat for Windows.). A Tomcat restart is needed. Note that <strong>a lot</strong> of information is logged and you&#8217;re log files will grow rather quickly. Please remember to<strong> turn this off </strong>in regular production mode.</p>
<p>Hopefully this will help when configuring MEM to authenticate it&#8217;s users against a LDAP directory.</p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2010/10/11/configuring-mysql-enterprise-monitor-to-authenticate-from-ldap/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Setting up OpenLDAP for MySQL Enterprise Monitor</title>
		<link>http://lmorgado.com/blog/2010/10/11/setting-up-openldap-for-mysql-enterprise-monitor/</link>
		<comments>http://lmorgado.com/blog/2010/10/11/setting-up-openldap-for-mysql-enterprise-monitor/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 20:00:02 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[LDAP]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL Enterprise Monitor]]></category>
		<category><![CDATA[OpenLDAP]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=197</guid>
		<description><![CDATA[How to setup OpenLDAP to use with MEM ]]></description>
			<content:encoded><![CDATA[<p>The latest 2.2 release of MySQL Enterprise Monitor (MEM) has the ability to authenticate against LDAP. I decided to test this setup and for that, I had to create and populate an OpenLDAP server, including STARTTLS/SSL certificates. This guide was done on CentOS 5.5 but it shouldn&#8217;t be much different in other Linux/Unix distributions. First, start off by installing the packages with:</p>
<pre>root@shell&gt; yum install openldap openldap-clients openldap-servers</pre>
<p>Then head to /etc/openldap where you can set you domain and the DN for the LDAP manager user.  I&#8217;ve inserted some useful comments into the slapd.conf file. Lines without comments have not been changed from the default slapd.conf file.</p>
<pre>shell&gt; grep -v "^#" /etc/openldap/slapd.conf | grep -v "^$"
include		/etc/openldap/schema/core.schema
include		/etc/openldap/schema/cosine.schema
include		/etc/openldap/schema/inetorgperson.schema
include		/etc/openldap/schema/nis.schema
allow bind_v2
pidfile		/var/run/openldap/slapd.pid
argsfile	/var/run/openldap/slapd.args</pre>
<pre>#The lines below are for SSL and STARTTLS.
#I'll show you how to generate certs later on
TLSCipherSuite HIGH:MEDIUM:-SSLv2
TLSCACertificateFile /etc/openldap/ssl/ca-cert.pem
TLSCertificateFile /etc/openldap/ssl/server-cert.pem
TLSCertificateKeyFile /etc/openldap/ssl/server-key.pem
#This allows ldapsearch command to connect without a client cert
TLSVerifyClient never</pre>
<pre>database	bdb
# this is your domain. I used example.com for my tests.
suffix		"dc=example,dc=com"
# this is the "username" of the LDAP admin for this domain
rootdn		"cn=Manager,dc=example,dc=com"
# this is the encripted password. To generate a SSHA password use slappasswd.
rootpw {SSHA}8diJsdIYFRr/wt7vqk3SGj6b/ZZZ21eno</pre>
<pre>directory	/var/lib/ldap
index objectClass                       eq,pres
index ou,cn,mail,surname,givenname      eq,pres,sub
index uidNumber,gidNumber,loginShell    eq,pres
index uid,memberUid                     eq,pres,sub
index nisMapName,nisMapEntry            eq,pres,sub</pre>
<p>If for some reason, you need to compile your own version of OpenLDAP, see this guide:<br />
<a href="http://www.openldap.org/doc/admin24/quickstart.html">http://www.openldap.org/doc/admin24/quickstart.html</a></p>
<p>The next step is to generate our certificates. First we generate the Certificate Authority and the LDAP Server certificates. One important thing is to set the CN attribute to your server&#8217;s hostname in both certificates. You can run the hostname command in the shell to find that out. This is the same hostname you will be using in the MEM setup or to test with the ldapsearch command line utility.</p>
<pre># Create CA and Server Certs
shell&gt; openssl genrsa 2048 &gt; ca-key.pem
shell&gt; openssl req -new -x509 -nodes -days 1000 -key ca-key.pem &gt; ca-cert.pem
shell&gt; openssl req -newkey rsa:2048 -days 1000 -nodes -keyout server-key.pem &gt; server-req.pem
shell&gt; openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 &gt; server-cert.pem</pre>
<p>These files should be located under /etc/openldap/ssl and the server key needs to be chmoded:</p>
<pre>shell&gt; chmod 600 /etc/openldap/server-key.pem</pre>
<p>Then we create the certificate for our client utilities, and let openldap know about it:</p>
<pre># Create client certificate
shell&gt; openssl req -newkey rsa:2048 -days 1000 -nodes -keyout client-key.pem &gt; client-req.pem
shell&gt; openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 &gt; client-cert.pem</pre>
<pre>shell&gt; cat /etc/openldap/ldap.conf
#
# LDAP Defaults
#</pre>
<pre># See ldap.conf(5) for details
# This file should be world readable but not world writable.</pre>
<pre>#BASE	dc=example, dc=com
#URI	ldap://ldap.example.com ldap://ldap-master.example.com:666</pre>
<pre>#SIZELIMIT	12
#TIMELIMIT	15
#DEREF		never
#TLS_CACERTDIR /etc/openldap/cacerts
TLS_CACERT /etc/openldap/ssl/ca-cert.pem</pre>
<p>Here are how the permissions on these files look like for me:</p>
<pre>shell&gt; ls -la /etc/openldap/ssl/
total 40K
drwxr-xr-x 2 root root 4.0K Jun 23 13:53 .
drwxr-xr-x 5 root root 4.0K Jun 25 20:59 ..
-rw-r--r-- 1 root root 1.5K Jun 23 13:51 ca-cert.pem
-rw-r--r-- 1 root root 1.7K Jun 23 13:51 ca-key.pem
-rw-r--r-- 1 root root 1.2K Jun 23 13:53 client-cert.pem
-rw-r--r-- 1 root root 1.7K Jun 23 13:53 client-key.pem
-rw-r--r-- 1 root root 1.1K Jun 23 13:53 client-req.pem
-rw-r--r-- 1 root root 1.2K Jun 23 13:52 server-cert.pem
-rw------- 1 ldap root 1.7K Jun 23 13:52 server-key.pem
-rw-r--r-- 1 root root 1.1K Jun 23 13:52 server-req.pem</pre>
<p>Next enable SSL for OpenLDAP and start up the server:</p>
<pre>shell&gt; grep -v "^#" /etc/sysconfig/ldap | grep -v "^$"
ULIMIT_SETTINGS=
STOP_DELAY=3s
SLAPD_LDAP=yes
SLAPD_LDAPS=yes
SLAPD_LDAPI=no</pre>
<pre>shell&gt; /etc/init.d/ldap start
Checking configuration files for slapd:  bdb_db_open: Warning - No DB_CONFIG file found in directory /var/lib/ldap: (2)
Expect poor performance for suffix dc=example,dc=com.
config file testing succeeded                                                           [  OK  ]
Starting slapd:                                            [  OK  ]</pre>
<pre>shell&gt; ps aux | grep slapd
ldap     25224  0.0  2.3 392036 191288 ?       Ssl  21:01   0:00 /usr/sbin/slapd -h ldap:/// ldaps:/// -u ldap</pre>
<p>Don&#8217;t worry about the warning. Let&#8217;s try and query the LDAP directory now:</p>
<pre>shell&gt; ldapsearch -x -h localhost -b 'dc=example,dc=com'
# extended LDIF
#
# LDAPv3
# base  with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#</pre>
<pre># search result
search: 2
result: 32 No such object</pre>
<pre># numResponses: 1</pre>
<p>As we can see, there are no entries yet. So let&#8217;s populate the directory with this <a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/1.txt"></a><a href="http://lmorgado.com/blog/wp-content/uploads/2010/06/mem-ldap.ldif_.txt">LDIF file</a>. You will be prompted for your password. It&#8217;s the one used to setup /etc/openldap/slapd.conf.</p>
<pre>shell&gt; ldapadd -x -D "cn=Manager,dc=example,dc=com" -W -f mem-ldap.ldif.txt
Enter LDAP Password:
adding new entry "dc=example,dc=com"</pre>
<pre>adding new entry "ou=People,dc=example,dc=com"</pre>
<pre>adding new entry "uid=user1,ou=People,dc=example,dc=com"</pre>
<pre>adding new entry "uid=user2,ou=People,dc=example,dc=com"</pre>
<pre>adding new entry "ou=groups,dc=example,dc=com"</pre>
<pre>adding new entry "cn=admin,ou=groups,dc=example,dc=com"</pre>
<pre>adding new entry "cn=dba,ou=groups,dc=example,dc=com"</pre>
<p>And now we can see the results with:</p>
<pre>shell&gt; ldapsearch -x -H ldap:///localhost -b 'dc=example,dc=com'
# extended LDIF
#
# LDAPv3
# base &lt;dc=example,dc=com&gt; with scope subtree
# filter: (objectclass=*)
# requesting: ALL
#</pre>
<pre># example.com
dn: dc=example,dc=com
objectClass: domain
objectClass: top
dc: example</pre>
<pre># People, example.com
dn: ou=People,dc=example,dc=com
objectClass: organizationalUnit
objectClass: top
ou: People</pre>
<pre># user1, People, example.com
dn: uid=user1,ou=People,dc=example,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
cn: Aaren Atp
sn: Atp
description: This is the description for Aaren Atp.
employeeNumber: 1
givenName: Aaren
homePhone: +1 280 375 4325
initials: ALA
l: New Haven
mail: user.1@maildomain.net
mobile: +1 680 734 6300
ou: admin
pager: +1 850 883 8888
postalAddress: Aaren Atp$70110 Fourth Street$New Haven, OH  93694
postalCode: 936942
st: OH
street: 70110 Fourth Street
telephoneNumber: +1 390 103 6917
uid: user1
userPassword:: e1NTSEF9Z0tsZjU4cm50Wit4b045N0U4cWlldVJQK1RMOVAzTGw=</pre>
<pre># user2, People, example.com
dn: uid=user2,ou=People,dc=example,dc=com
objectClass: person
objectClass: inetOrgPerson
objectClass: organizationalPerson
objectClass: top
cn: Aaren Atp
sn: Atp
description: This is the description for Aaren Atp.
employeeNumber: 2
givenName: Aaren
homePhone: +1 280 375 4325
initials: ALA
l: New Haven
mail: user2@maildomain.net
mobile: +1 680 734 6300
ou: dba
pager: +1 850 883 8888
postalAddress: Aaren Atp$70110 Fourth Street$New Haven, OH  93694
postalCode: 936941
st: OH
street: 70110 Fourth Street
telephoneNumber: +1 390 103 6917
uid: user2
userPassword:: e1NTSEF9Z0tsZjU4cm50Wit4b045N0U4cWlldVJQK1RMOVAzTGw=</pre>
<pre># groups, example.com
dn: ou=groups,dc=example,dc=com
objectClass: organizationalUnit
ou: groups</pre>
<pre># admin, groups, example.com
dn: cn=admin,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
cn: admin
uniqueMember: uid=user1,ou=People,dc=example,dc=com</pre>
<pre># dba, groups, example.com
dn: cn=dba,ou=groups,dc=example,dc=com
objectClass: groupOfUniqueNames
cn: dba
uniqueMember: uid=user2,ou=People,dc=example,dc=com</pre>
<pre># search result
search: 2
result: 0 Success</pre>
<pre># numResponses: 8
# numEntries: 7</pre>
<p>You should also test encrypted connections, first with STARTTLS, by adding the -ZZ option:</p>
<pre>shell&gt; ldapsearch -x -h localhost -ZZ -b 'dc=example,dc=com'</pre>
<p>You can also do it with SSL (ldaps), but this has been deprecated in LDAPv3:</p>
<pre>shell&gt; ldapsearch -x -H ldaps:///localhost -b 'dc=example,dc=com'</pre>
<p>If you need to look at the OpenLDAP log files, you should enable them  in syslog.conf:</p>
<pre># Log LDAP stuff
local4.*                        /var/log/ldap.log</pre>
<p>By default, OpenLDAP writes to the LOG_LOCAL 4 facility. You should  also set the loglevel to the amount of detail needed. Either check <em>man  slapd.conf </em>or the <a title="OpenLDAP slapd.conf" href="http://www.openldap.org/doc/admin24/slapdconfig.html" target="_blank">documentation</a> for the available levels.</p>
<p>At the moment, we have a running openldap server which is populated with two test users, ready to be used by MEM. In the next <a href="http://lmorgado.com/blog/2010/10/11/configuring-mysql-enterprise-monitor-to-authenticate-from-ldap/">post</a>, I will discuss how to setup MEM to authenticate against our LDAP server. If you need to manipulate your LDAP directory and need a graphical tool, I found <a href="http://directory.apache.org/studio/">Apache Directory Studio</a> to be very nice.</p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2010/10/11/setting-up-openldap-for-mysql-enterprise-monitor/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Connecting JBDC to MySQL Enterprise Monitor&#8217;s Query Analyzer</title>
		<link>http://lmorgado.com/blog/2010/10/11/connecting-jbdc-to-mysql-enterprise-monitors-query-analyzer/</link>
		<comments>http://lmorgado.com/blog/2010/10/11/connecting-jbdc-to-mysql-enterprise-monitors-query-analyzer/#comments</comments>
		<pubDate>Mon, 11 Oct 2010 19:00:04 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[*NIX]]></category>
		<category><![CDATA[Databases]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[JDBC]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL Enterprise Monitor]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=182</guid>
		<description><![CDATA[With the release of MySQL Enterprise Monitor (MEM) 2.2, there is now the ability to monitor queries using the Query Analyzer (QUAN) without needing the agent proxy to be running. You can use a .NET or JDBC connector plugin to directly gather the query statistics. In the example below, we will use the MySQL Enterprise [...]]]></description>
			<content:encoded><![CDATA[<p>With the release of <a href="https://enterprise.mysql.com/monitoring/">MySQL Enterprise Monitor</a> (MEM) 2.2, there is now the ability to monitor queries using the Query Analyzer (QUAN) without needing the agent proxy to be running. You can use a .NET or JDBC connector plugin to directly gather the query statistics. In the example below, we will use the MySQL Enterprise Plugin for Connector/J.</p>
<p>First, make sure both the Connector/J, the Connector/J plugin and the Apache Commons     Logging jars are in the $CLASSPATH. At the time of writing, these are the files needed:</p>
<p><em>mysql-connector-java-5.1.12-bin.jar<br />
c-java-mysql-enterprise-plugin-1.0.0.42.jar<br />
required/commons-logging-1.1.1.jar</em></p>
<p>Then, add the plugin to the connection string so that it changes from something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">conn <span style="color: #339933;">=</span>	<span style="color: #003399;">DriverManager</span>.<span style="color: #006633;">getConnection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jdbc:mysql://localhost:3306/test?&quot;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;user=root&amp;password=PASSWORD&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>to something like this:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;">conn <span style="color: #339933;">=</span> <span style="color: #003399;">DriverManager</span>.<span style="color: #006633;">getConnection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jdbc:mysql://localhost:3306/test?&quot;</span>
       <span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;user=root&amp;password=PASSWORD&quot;</span>
       <span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;&amp;statementInterceptors=com.mysql.etools.jdbc.StatementPerformanceCounters&quot;</span>
       <span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;&amp;serviceManagerUrl=http://memserverhost.com:18080/&quot;</span>
       <span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;&amp;serviceManagerUser=agent&amp;serviceManagerPassword=AGENTPASSWORD&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>Here is the full example code:</p>

<div class="wp_syntax"><div class="code"><pre class="java" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">import</span> <span style="color: #006699;">java.sql.*</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">// Notice, do not import com.mysql.jdbc.*</span>
<span style="color: #666666; font-style: italic;">// or you will have problems!</span>
&nbsp;
<span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">class</span> LoadDriver <span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">static</span> <span style="color: #000066; font-weight: bold;">void</span> main<span style="color: #009900;">&#40;</span><span style="color: #003399;">String</span><span style="color: #009900;">&#91;</span><span style="color: #009900;">&#93;</span> args<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
        <span style="color: #000000; font-weight: bold;">try</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// The newInstance() call is a work around for some</span>
            <span style="color: #666666; font-style: italic;">// broken Java implementations</span>
&nbsp;
           	<span style="color: #000000; font-weight: bold;">Class</span>.<span style="color: #006633;">forName</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;com.mysql.jdbc.Driver&quot;</span><span style="color: #009900;">&#41;</span>.<span style="color: #006633;">newInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
	        <span style="color: #003399;">Connection</span> conn <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">null</span><span style="color: #339933;">;</span>
		conn <span style="color: #339933;">=</span>	<span style="color: #003399;">DriverManager</span>.<span style="color: #006633;">getConnection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;jdbc:mysql://127.0.0.1:33306/test?&quot;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;user=root&amp;password=PASSWORD&quot;</span><span style="color: #339933;">+</span><span style="color: #0000ff;">&quot;&amp;statementInterceptors=com.mysql.etools.jdbc.StatementPerformanceCounters&amp;serviceManagerUrl=http://memserverhostname.com:18080/&amp;serviceManagerUser=agent&amp;serviceManagerPassword=AGENTPASSWORD&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
		<span style="color: #666666; font-style: italic;">//Get a Statement object</span>
	      	<span style="color: #003399;">Statement</span> stmt <span style="color: #339933;">=</span> conn.<span style="color: #006633;">createStatement</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    		<span style="color: #003399;">ResultSet</span> rs <span style="color: #339933;">=</span> stmt.<span style="color: #006633;">executeQuery</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;SELECT SLEEP(10)&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		<span style="color: #003399;">System</span>.<span style="color: #006633;">out</span>.<span style="color: #006633;">println</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">&quot;Closing connection&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		rs.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
		conn.<span style="color: #006633;">close</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span> <span style="color: #000000; font-weight: bold;">catch</span> <span style="color: #009900;">&#40;</span><span style="color: #003399;">Exception</span> ex<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #666666; font-style: italic;">// handle the error</span>
	    ex.<span style="color: #006633;">printStackTrace</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>Now, when you Java application runs queries, they will be analyzed by QUAN. In my example code, there is a sleep call for 10 seconds. You can clearly see that this query was caught by QUAN:</p>
<p><a href="http://lmorgado.com/blog/wp-content/uploads/2010/05/quan-java.png"><img class="alignleft size-full wp-image-183" title="Slow queries fed to QUAN using the Connector/J plugin" src="http://lmorgado.com/blog/wp-content/uploads/2010/05/quan-java.png" alt="Slow queries fed to QUAN using the Connector/J plugin" width="1128" height="184" /></a></p>
<p>This now eliminates the need for the monitoring agent to be running it&#8217;s own instance of mysql-proxy for QUAN. Java and .NET applications can simply use the interceptor, saving on resources.</p>
<p>Of course, prior to setting this up, you should always check the <a href="https://enterprise.mysql.com/docs/monitor/2.2/en/mem-qanal-using.html#mem-qanal-using-cj">online documentation.</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2010/10/11/connecting-jbdc-to-mysql-enterprise-monitors-query-analyzer/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Locks (and a bit of the Query Cache)</title>
		<link>http://lmorgado.com/blog/2008/09/10/mysql-locks-and-a-bit-of-the-query-cache/</link>
		<comments>http://lmorgado.com/blog/2008/09/10/mysql-locks-and-a-bit-of-the-query-cache/#comments</comments>
		<pubDate>Wed, 10 Sep 2008 20:52:10 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[locking]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[query cache]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=49</guid>
		<description><![CDATA[MySQL uses locks for concurrency control. Whenever a client/thread acquires a lock, it will have exclusive access to that table or row (depending on the granularity of the lock). Other clients however, will be prevented from writing and possibly reading to/from the locked resource. The two main existing locks are: READ LOCK &#8211; A read [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL uses locks for concurrency control. Whenever a client/thread acquires a lock, it will have exclusive access to that table or row (depending on the granularity of the lock). Other clients however, will be prevented from writing and possibly reading to/from the locked resource. The two main existing locks are:</p>
<p><strong>READ LOCK</strong> &#8211; A read lock will allow the other clients to read from the locked resource but not write to it.<br />
<strong>WRITE LOCK</strong> &#8211; a write lock will prevent the other clients from reading or writing to the locked resource.</p>
<p>Also, different storage engines have different lock granularity. For example, MyISAM will lock the whole table while InnoDB will only lock the rows it needs.</p>
<p>Let&#8217;s try this out using a MyISAM table. We open two concurrent sessions and in the first lock the City table from the world database (get it <a title="MySQL Docs" href="http://dev.mysql.com/doc/" target="_blank">here</a>).</p>
<p><em>Session 1:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">LOCK</span> <span style="color: #990099; font-weight: bold;">TABLE</span> City <span style="color: #990099; font-weight: bold;">READ</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.19</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span>
<span style="color: #CC0099;">+----+------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span> ID <span style="color: #CC0099;">|</span> Name <span style="color: #CC0099;">|</span> CountryCode <span style="color: #CC0099;">|</span> District <span style="color: #CC0099;">|</span> Population <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span>  <span style="color: #008080;">1</span> <span style="color: #CC0099;">|</span>      <span style="color: #CC0099;">|</span> AFG         <span style="color: #CC0099;">|</span> Kabol    <span style="color: #CC0099;">|</span>    <span style="color: #008080;">1780000</span> <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+------+-------------+----------+------------+</span>
<span style="color: #008080;">1</span> row <span style="color: #990099; font-weight: bold;">in</span> <span style="color: #990099; font-weight: bold;">set</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">1.09</span> sec<span style="color: #FF00FF;">&#41;</span>
&nbsp;
mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">DELETE</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">WHERE</span> ID<span style="color: #CC0099;">=</span><span style="color: #008080;">1</span><span style="color: #000033;">;</span></pre></div></div>

<p>Here we can see that in Session 2, we are able to read from the locked table, but the query just hangs when trying to write. This happens because Session 1 has acquired a read lock on the table. As soon as Session 1 releases the lock, Session 2 is able to write to the table.</p>
<p><em>Session 1:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> UNLOCK <span style="color: #990099; font-weight: bold;">TABLES</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.05</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">DELETE</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">WHERE</span> ID<span style="color: #CC0099;">=</span><span style="color: #008080;">1</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">1</span> row affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">1</span> <span style="color: #000099;">min</span> <span style="color: #008080;">39.07</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p>We can see that the lock was in place for over a minute before Session 1 released it and Session 2 was able to grab it. Now let&#8217;s see what happens with a WRITE LOCK.</p>
<p><em>Session 1:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">LOCK</span> <span style="color: #990099; font-weight: bold;">TABLE</span> City <span style="color: #990099; font-weight: bold;">WRITE</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.05</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">DELETE</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">WHERE</span> ID<span style="color: #CC0099;">=</span><span style="color: #008080;">2</span><span style="color: #000033;">;</span>
Query aborted by Ctrl<span style="color: #CC0099;">+</span>C
ERROR <span style="color: #008080;">1317</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">70100</span><span style="color: #FF00FF;">&#41;</span>: Query execution was interrupted
mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span></pre></div></div>

<p>In the example above I tried to write to City, saw that it hung waiting for the lock and then aborted the query. I then tried to do a read. Due to the write lock, Session 2 can&#8217;t do a read or a write until Session 1 releases the lock:</p>
<p><em>Session 1:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> UNLOCK <span style="color: #990099; font-weight: bold;">TABLES</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.00</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;"><span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span> ID <span style="color: #CC0099;">|</span> Name     <span style="color: #CC0099;">|</span> CountryCode <span style="color: #CC0099;">|</span> District <span style="color: #CC0099;">|</span> Population <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span>  <span style="color: #008080;">2</span> <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span> AFG         <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span>     <span style="color: #008080;">237500</span> <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #008080;">1</span> row <span style="color: #990099; font-weight: bold;">in</span> <span style="color: #990099; font-weight: bold;">set</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">25.64</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p>One thing that can confuse you is the following situation. Say you read something from a table before issuing any locks:</p>
<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span> ID <span style="color: #CC0099;">|</span> Name     <span style="color: #CC0099;">|</span> CountryCode <span style="color: #CC0099;">|</span> District <span style="color: #CC0099;">|</span> Population <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span>  <span style="color: #008080;">2</span> <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span> AFG         <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span>     <span style="color: #008080;">237500</span> <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #008080;">1</span> row <span style="color: #990099; font-weight: bold;">in</span> <span style="color: #990099; font-weight: bold;">set</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.00</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p>Then you write lock the table (preventing reads and writes from other sessions) and try the read again:</p>
<p><em>Session 1:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">LOCK</span> <span style="color: #990099; font-weight: bold;">TABLE</span> City <span style="color: #990099; font-weight: bold;">WRITE</span><span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.00</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span> ID <span style="color: #CC0099;">|</span> Name     <span style="color: #CC0099;">|</span> CountryCode <span style="color: #CC0099;">|</span> District <span style="color: #CC0099;">|</span> Population <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #CC0099;">|</span>  <span style="color: #008080;">2</span> <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span> AFG         <span style="color: #CC0099;">|</span> Qandahar <span style="color: #CC0099;">|</span>     <span style="color: #008080;">237500</span> <span style="color: #CC0099;">|</span>
<span style="color: #CC0099;">+----+----------+-------------+----------+------------+</span>
<span style="color: #008080;">1</span> row <span style="color: #990099; font-weight: bold;">in</span> <span style="color: #990099; font-weight: bold;">set</span> <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.00</span> sec<span style="color: #FF00FF;">&#41;</span></pre></div></div>

<p>Wow! Session 2 was able to read the City table even though Session 1 has write locked it! What the hell is happening? The truth is that MySQL&#8217;s query cache is tricking you. The query cache gets checked beforehand and if the query is cached, it won&#8217;t even need to look at the table or care about locks. One way to test this is by issuing a different read query that&#8217;s not in cache:</p>
<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">2</span><span style="color: #000033;">;</span></pre></div></div>

<p>It hangs as expected, waiting for the write lock to be released. Remember that MySQL does a hash on the SQL query and if it&#8217;s different (even in case), it won&#8217;t use the query cache. We can also try the same query after emptying the query cache:</p>
<p><em>Session 2:</em></p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> RESET QUERY CACHE<span style="color: #000033;">;</span>
Query OK<span style="color: #000033;">,</span> <span style="color: #008080;">0</span> rows affected <span style="color: #FF00FF;">&#40;</span><span style="color: #008080;">0.00</span> sec<span style="color: #FF00FF;">&#41;</span>
&nbsp;
mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">1</span><span style="color: #000033;">;</span></pre></div></div>

<p>Once again, this leaves us waiting on the lock.</p>
<p>Concurrency is complicated stuff and there is a lot of ground to cover. There are other ways to do locks (eg: GET_LOCK(), SELECT &#8230; FOR UPDATE) with different purposes and applications. You can find out a little bit more in the excellent MySQL documentation (<a title="Lock Tables" href="http://dev.mysql.com/doc/refman/5.0/en/lock-tables.html" target="_blank">1</a> <a title="Locking Issues" href="http://dev.mysql.com/doc/refman/5.1/en/locking-issues.html " target="_blank">2</a> <a title="InnoDB Transactions" href=" http://dev.mysql.com/doc/refman/5.0/en/innodb-transaction-model.html" target="_blank">3</a>)</p>
<p>The query cache is very handy and allows you to boost performance greatly. As with any cache, it can be confusing, so you should remember that it will serve out cached results even when you don&#8217;t expect them (it can turn it off though). You can find more info <a title="Query Cache" href="http://dev.mysql.com/doc/refman/5.1/en/query-cache.html" target="_blank">here</a>.</p>
<p>One thing you can do to get prevent your queries being served from the query cache is to issue them like this:</p>

<div class="wp_syntax"><div class="code"><pre class="mysql" style="font-family:monospace;">mysql<span style="color: #CC0099;">&gt;</span> <span style="color: #990099; font-weight: bold;">SELECT</span> <span style="color: #990099; font-weight: bold;">SQL_NO_CACHE</span> <span style="color: #CC0099;">*</span> <span style="color: #990099; font-weight: bold;">FROM</span> City <span style="color: #990099; font-weight: bold;">LIMIT</span> <span style="color: #008080;">2</span><span style="color: #000033;">;</span></pre></div></div>

<p>I&#8217;ll close off with some notes about locking:</p>
<ol>
<li>WRITE locks have higher priority than READ locks</li>
<li>When you issue a second LOCK TABLE, it will implicitly unlock all previously held locks.</li>
<li>To lock mutiple tables, you need to lock them simultaneously. Eg:LOCK TABLE City WRITE, Country READ;</li>
</ol>
<p>Happy lock picking!</p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2008/09/10/mysql-locks-and-a-bit-of-the-query-cache/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL Passwordless Login</title>
		<link>http://lmorgado.com/blog/2008/08/12/mysql-passwordless-login/</link>
		<comments>http://lmorgado.com/blog/2008/08/12/mysql-passwordless-login/#comments</comments>
		<pubDate>Tue, 12 Aug 2008 17:46:26 +0000</pubDate>
		<dc:creator>Leandro Morgado</dc:creator>
				<category><![CDATA[Databases]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://lmorgado.com/blog/?p=19</guid>
		<description><![CDATA[MySQL allows user specific options to be placed in a user options file under your home directory. This is handy if you use automated scripts or want to avoid typing in your MySQL user&#8217;s password everytime you login in. To do this, create the ~/.my.cnf with the options below: &#91;client&#93; user=mysqlusername password=mysqlpassword Then make sure [...]]]></description>
			<content:encoded><![CDATA[<p>MySQL allows user specific options to be placed in a user options file under your home directory. This is handy if you use automated scripts or want to avoid typing in your MySQL user&#8217;s password everytime you login in. To do this, create the <strong>~/.my.cnf</strong> with the options below:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #7a0874; font-weight: bold;">&#91;</span>client<span style="color: #7a0874; font-weight: bold;">&#93;</span>
<span style="color: #007800;">user</span>=mysqlusername
<span style="color: #007800;">password</span>=mysqlpassword</pre></div></div>

<p>Then make sure no one else on the system can read this file. It&#8217;s essential for security as it contains your password in clear text!</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ <span style="color: #c20cb9; font-weight: bold;">chmod</span> <span style="color: #000000;">600</span> ~<span style="color: #000000; font-weight: bold;">/</span>.my.cnf
$ <span style="color: #c20cb9; font-weight: bold;">ls</span> <span style="color: #660033;">-l</span> ~<span style="color: #000000; font-weight: bold;">/</span>.my.cnf
<span style="color: #660033;">-rw-------</span> <span style="color: #000000;">1</span> alice alice <span style="color: #000000;">36</span> Aug <span style="color: #000000;">12</span> <span style="color: #000000;">17</span>:<span style="color: #000000;">49</span> <span style="color: #000000; font-weight: bold;">/</span>home<span style="color: #000000; font-weight: bold;">/</span>alice<span style="color: #000000; font-weight: bold;">/</span>.my.cnf</pre></div></div>

<p>Now you can just type mysql to login. Note that this will work for other MySQL clients like mysqldump. And you can always override the .my.cnf settings in the command line. For example:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;">$ mysql <span style="color: #660033;">-ubob</span> <span style="color: #660033;">-pbobspassword</span></pre></div></div>

<p>You can add other parameters to this file. For a full reference check out:<br />
<a href="http://dev.mysql.com/doc/refman/5.1/en/option-files.html">http://dev.mysql.com/doc/refman/5.1/en/option-files.html</a></p>
]]></content:encoded>
			<wfw:commentRss>http://lmorgado.com/blog/2008/08/12/mysql-passwordless-login/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

