<?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>Altentee &#187; Performance &#38; Test Automation Experts &#187; mysql</title>
	<atom:link href="http://altentee.com/tag/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://altentee.com</link>
	<description>Performance and Test Automation Experts</description>
	<lastBuildDate>Sat, 12 Jun 2010 00:35:08 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Securing MySQL Passwords</title>
		<link>http://altentee.com/2010/securing-mysql-passwords/</link>
		<comments>http://altentee.com/2010/securing-mysql-passwords/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 20:54:27 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=746</guid>
		<description><![CDATA[<p>There&#8217;s been a bit of buzz lately where MySQL databases have been compromised and user passwords being stored in plain text. Bad fu. It&#8217;s pretty simple to encrypt passwords in MySQL, here&#8217;s how you do it.</p>
<p>I&#8217;m using MySQL&#8217;s AES which is better than older standards. Basically 128 bit key encryption &#8230;</p>
<p>To begin, let&#8217;s create a [...]]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s been a <a href="http://www.techcrunch.com/2009/12/14/rockyou-hacked/">bit of buzz</a> lately where MySQL databases have been compromised and user passwords being stored in plain text. Bad fu. It&#8217;s pretty simple to encrypt passwords in MySQL, here&#8217;s how you do it.</p>
<p><span id="more-746"></span>I&#8217;m using MySQL&#8217;s <a href="http://en.wikipedia.org/wiki/Advanced_Encryption_Standard">AES</a> which is better than older standards. Basically 128 bit key encryption &#8230;</p>
<p>To begin, let&#8217;s create a demonstration table. e.g.<br />
CREATE TABLE users ( user_name VARCHAR(20) NOT NULL, user_password BLOB );</p>
<p>So now we have a simple table with a user_name field and user_password field. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">DESCRIBE</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">FIELD</span>         <span style="color: #66cc66;">|</span> Type        <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">KEY</span> <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #66cc66;">|</span> Extra <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span>
<span style="color: #66cc66;">|</span> user_name     <span style="color: #66cc66;">|</span> varchar<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">20</span><span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">|</span> NO   <span style="color: #66cc66;">|</span>     <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>    <span style="color: #66cc66;">|</span>       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">|</span> user_password <span style="color: #66cc66;">|</span> blob        <span style="color: #66cc66;">|</span> YES  <span style="color: #66cc66;">|</span>     <span style="color: #66cc66;">|</span> <span style="color: #993333; font-weight: bold;">NULL</span>    <span style="color: #66cc66;">|</span>       <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">---------------+-------------+------+-----+---------+-------+</span></pre></div></div>

<p>If we were creating a new user we would insert using the AES_ENCRYPT function. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'tim.koopmans'</span><span style="color: #66cc66;">,</span> AES_ENCRYPT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'mypassword'</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>In this case I&#8217;ve used AES_ENCRYPT which encrypts a             string and returns a binary string. The AES             (Advanced Encryption Standard) algorithm is encoded with a 128-bit key. The second parameter is the key string, important to keep that secure!</p>
<p>On its own, this offers a good level of security. If the database was compromised the hacker will see information like this. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span>
<span style="color: #66cc66;">|</span> user_name    <span style="color: #66cc66;">|</span> user_password    <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span>
<span style="color: #66cc66;">|</span> tim<span style="color: #66cc66;">.</span>koopmans <span style="color: #66cc66;">|</span> ??iu?hQ:???Ti?<span style="color: #66cc66;">&#125;</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+------------------+</span></pre></div></div>

<p>The problem with this, is that the user_password field can still be &#8216;guessed&#8217; via brute force methods. Every password that is the same i.e. &#8216;mypassword&#8217; will also have the same binary string.</p>
<p>You can add a <a href="http://en.wikipedia.org/wiki/Salt_%28cryptography%29">salt</a> to this by prefixing random digits to the plain text password before you encrypt. For example, we can use the first 12 digits of a UUID. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">INSERT</span> <span style="color: #993333; font-weight: bold;">INTO</span> users <span style="color: #993333; font-weight: bold;">VALUES</span> <span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">'joe.blow'</span><span style="color: #66cc66;">,</span> AES_ENCRYPT<span style="color: #66cc66;">&#40;</span>CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #993333; font-weight: bold;">LEFT</span><span style="color: #66cc66;">&#40;</span>UUID<span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">12</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'mypassword'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span>;</pre></div></div>

<p>The result set now looks like this if compromised.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">*</span> <span style="color: #993333; font-weight: bold;">FROM</span> users;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span>
<span style="color: #66cc66;">|</span> user_name    <span style="color: #66cc66;">|</span> user_password                    <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span>
<span style="color: #66cc66;">|</span> tim<span style="color: #66cc66;">.</span>koopmans <span style="color: #66cc66;">|</span> ??iu?hQ:???Ti?<span style="color: #66cc66;">&#125;</span>                  <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">|</span> joe<span style="color: #66cc66;">.</span>blow     <span style="color: #66cc66;">|</span> ?M<span style="color: #66cc66;">&#125;</span><span style="color: #cc66cc;">69</span>?H?<span style="color: #cc66cc;">0</span>?H<span style="color: #66cc66;">&#125;</span>?<span style="color: #66cc66;">/</span><span style="color: #66cc66;">&#123;</span><span style="color: #66cc66;">.</span>?we<span style="color: #66cc66;">|</span>?A?P7ZD?R?   <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">--------------+----------------------------------+</span></pre></div></div>

<p>Every password that is encrypted should look different which will further complicate dictionary attacks.</p>
<blockquote><p>To determine a password from a stolen hash, an attacker cannot simply try common passwords (such as English language words or names). Rather, they must calculate the hashes of random characters (at least for the portion of the input they know is the salt), which is much slower.</p></blockquote>
<p>For best results, the value/length of your salt should be kept secret (and separate from your database). You should also keep the key secret of course!</p>
<p>Now if we ever need to extract the password we use the AES_DECRYPT function. e.g.</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;">mysql&amp;gt; <span style="color: #993333; font-weight: bold;">SELECT</span> SUBSTR<span style="color: #66cc66;">&#40;</span>AES_DECRYPT<span style="color: #66cc66;">&#40;</span>user_password<span style="color: #66cc66;">,</span> <span style="color: #ff0000;">'Q4QjOyKANXj3qO'</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #cc66cc;">13</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">AS</span> password <span style="color: #993333; font-weight: bold;">FROM</span> users <span style="color: #993333; font-weight: bold;">WHERE</span> user_name <span style="color: #66cc66;">=</span> <span style="color: #ff0000;">'joe.blow'</span>;
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span>
<span style="color: #66cc66;">|</span> password   <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span>
<span style="color: #66cc66;">|</span> mypassword <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">------------+</span></pre></div></div>

<p>In this case we know the first 12 digits were the salt so I used SUBSTR after decrypting the hash to get the original password.</p>
<p>A couple of caveats, encrypting passwords in this fashion is reversible i.e. If your key gets compromised, then the hacker has access to all your passwords. Another option is to reverse the plain text and key parameters of AES_ENCRYPT, where the user&#8217;s password now becomes the key, and the key becomes the plain text. Even if the database and key is compromised, it is hard to crack user passwords. You would not be able to recover lost passwords of course &#8230; Security through obscurity!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/securing-mysql-passwords/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Dynamic Data from JMeter JDBC Requests</title>
		<link>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/</link>
		<comments>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/#comments</comments>
		<pubDate>Tue, 05 Jan 2010 06:45:17 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[jdbc]]></category>
		<category><![CDATA[jmeter]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://altentee.com/?p=731</guid>
		<description><![CDATA[<p>A common requirement when load testing is to populate subsequent requests with dynamic data from previous requests. If you&#8217;re thinking about using a database to store static test data, such as usernames, paswords, credit card numbers etc then read on to find out how to extract this data at runtime and populate JMeter variables.</p>
<p>In this [...]]]></description>
			<content:encoded><![CDATA[<p>A common requirement when load testing is to populate subsequent requests with dynamic data from previous requests. If you&#8217;re thinking about using a database to store static test data, such as usernames, paswords, credit card numbers etc then read on to find out how to extract this data at runtime and populate JMeter variables.</p>
<p><span id="more-731"></span>In this example we&#8217;ll need to add a JDBC Connection Configuration to our test plan. This will define and control the way in which JMeter will access your database.</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.28.18-PM.png"><img class="alignleft size-full wp-image-732" title="Screen shot 2010-01-05 at 5.28.18 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.28.18-PM.png" alt="" width="647" height="423" /></a></p>
<p>Notice I&#8217;ve left the defaults for connection pool properties, although you may need to tweak this depending on how you&#8217;ll access the data. I&#8217;ve used a JDBC connection URL that accesses a local mysql server listening on port 3306. The database in use is called watirgrid</p>
<p>I&#8217;ve also defined the JDBC Driver class and specified the username / password to connect with.</p>
<p>Now we can make a JDBC request using the JDBC Request sampler. It will look something like this:<a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.31.52-PM.png"><img class="alignleft size-full wp-image-733" title="Screen shot 2010-01-05 at 5.31.52 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.31.52-PM.png" alt="" width="646" height="442" /></a></p>
<p>The Variable Name matches the JDBC Connection Config Variable Name i.e. mysql</p>
<p>I&#8217;m using a select statement that will print out results in a JSON-like format. That query is as follows:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;[&quot;</span><span style="color: #66cc66;">,</span>
GROUP_CONCAT<span style="color: #66cc66;">&#40;</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;{email:'&quot;</span><span style="color: #66cc66;">,</span>email<span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;'&quot;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span>
CONCAT<span style="color: #66cc66;">&#40;</span><span style="color: #ff0000;">&quot;,login_count:'&quot;</span><span style="color: #66cc66;">,</span>login_count<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;'}&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">,</span><span style="color: #ff0000;">&quot;]&quot;</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">AS</span> json <span style="color: #993333; font-weight: bold;">FROM</span> users</pre></div></div>

<p>In doing this, it will return a result set that looks like this:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #66cc66;">|</span> json                                            <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #66cc66;">|</span> <span style="color: #66cc66;">&#91;</span><span style="color: #66cc66;">&#123;</span>email:<span style="color: #ff0000;">'tim.koops@gmail.com'</span><span style="color: #66cc66;">,</span>login_count:<span style="color: #ff0000;">'1'</span><span style="color: #66cc66;">&#125;</span><span style="color: #66cc66;">&#93;</span> <span style="color: #66cc66;">|</span>
<span style="color: #66cc66;">+</span><span style="color: #808080; font-style: italic;">-------------------------------------------------+</span>
<span style="color: #cc66cc;">1</span> row <span style="color: #993333; font-weight: bold;">IN</span> <span style="color: #993333; font-weight: bold;">SET</span> <span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">0.00</span> sec<span style="color: #66cc66;">&#41;</span></pre></div></div>

<p>Now we need to add a Post Processor Regex Extractor to the JDBC request as follows:</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.34.39-PM.png"><img class="alignleft size-full wp-image-734" title="Screen shot 2010-01-05 at 5.34.39 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.34.39-PM.png" alt="" width="172" height="40" /></a></p>
<p>The reason we do this is so we can extract the results from the JSON string returned by the database query. For example, to extract and populate a variable called ${email} our PPRE would look like this:</p>
<p><a href="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.36.45-PM.png"><img class="alignleft size-full wp-image-735" title="Screen shot 2010-01-05 at 5.36.45 PM" src="http://altentee.com/wp-content/uploads/Screen-shot-2010-01-05-at-5.36.45-PM.png" alt="" width="652" height="236" /></a></p>
<p>Now we&#8217;re cooking! Add a Debug Sampler to confirm everything works as you&#8217;d expect. You should see results like this in the response data</p>
<pre>email=tim.koops@gmail.com
email_g=1
email_g0=email:'tim.koops@gmail.com'
email_g1=tim.koops@gmail.com
mysql=org.apache.jmeter.protocol.jdbc.config.DataSourceElement$DataSourceComponentImpl@10d69502
</pre>
<p>Attached is a demo test plan: <a href="http://altentee.com/wp-content/uploads/jdbc_example.jmx_.zip">jdbc_example.jmx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2010/dynamic-data-from-jmeter-jdbc-requests/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Sharing Data Between LoadRunner VUser Groups</title>
		<link>http://altentee.com/2009/sharing-data-between-loadrunner-vuser-groups/</link>
		<comments>http://altentee.com/2009/sharing-data-between-loadrunner-vuser-groups/#comments</comments>
		<pubDate>Thu, 19 Feb 2009 09:32:32 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[loadrunner]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/sharing-data-between-loadrunner-vuser-groups/</guid>
		<description><![CDATA[<p>When running multiple vuser groups with the same script i.e.
</p>
<p>If that script references a data file (for parameters) then that data file is shared by *all* vuser groups.
e.g. my parameter called {values} has

</p>
<p>When running, vuser group_b will error with these settings e.g.
</p>
<p>i.e.
</p>
<p>So 2 separate vuser groups still equals one shared parameter file (and settings).
Watch out [...]]]></description>
			<content:encoded><![CDATA[<p>When running multiple vuser groups with the same script i.e.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/02/pic11875.jpg' title='11875'><img src='http://90kts.com/blog/wp-content/uploads/2009/02/pic11875.jpg' alt='11875' /></a></p>
<p>If that script references a data file (for parameters) then that data file is shared by *all* vuser groups.<br />
e.g. my parameter called {values} has<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/02/pic24149.jpg' title='21419'><img src='http://90kts.com/blog/wp-content/uploads/2009/02/pic24149.jpg' alt='21419' /></a><br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/02/pic18190.jpg' title='18190'><img src='http://90kts.com/blog/wp-content/uploads/2009/02/pic18190.jpg' alt='18190' /></a></p>
<p>When running, vuser group_b will error with these settings e.g.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/02/pic03946.jpg' title='3946'><img src='http://90kts.com/blog/wp-content/uploads/2009/02/pic03946.jpg' alt='3946' /></a></p>
<p>i.e.<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/02/pic10798.jpg' title='748'><img src='http://90kts.com/blog/wp-content/uploads/2009/02/pic10798.jpg' alt='748' /></a></p>
<p>So 2 separate vuser groups still equals one shared parameter file (and settings).<br />
Watch out for this!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/sharing-data-between-loadrunner-vuser-groups/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Storing Milliseconds in MySQL</title>
		<link>http://altentee.com/2009/storing-milliseconds-in-mysql/</link>
		<comments>http://altentee.com/2009/storing-milliseconds-in-mysql/#comments</comments>
		<pubDate>Tue, 13 Jan 2009 05:14:14 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[mysql]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2009/storing-milliseconds-in-mysql/</guid>
		<description><![CDATA[<p>NOTE: This doesn&#8217;t generate a timestamp accurate to milliseconds. It just stores it in two fields. AFAIK there is no way to generate such a thing. It is accurately described here. Sorry for the confusion =)</p>
<p>Bug #8523 details MySQL&#8217;s deficiency in its ability to store and retrieve datetime values with millisecond or microsecond precision. When [...]]]></description>
			<content:encoded><![CDATA[<p><strong>NOTE</strong>: This doesn&#8217;t generate a timestamp accurate to milliseconds. It just stores it in two fields. AFAIK there is no way to generate such a thing. It is accurately described <a href="http://feedblog.org/2007/05/26/why-doesnt-mysql-support-millisecond-datetime-resolution/">here</a>. Sorry for the confusion =)</p>
<p><strong><a href="http://bugs.mysql.com/bug.php?id=8523">Bug #8523</a></strong> details MySQL&#8217;s deficiency in its ability to store and retrieve datetime values with millisecond or microsecond precision. When performance testing and perhaps storing trace logs or audit information in a MySQL table for later analysis, this shortfall is quite frustrating.</p>
<p>My hacky way to deal with this is to store the millisecond component as its own integer. Say for example you are interested in the difference between a Put datetime and Get datetime for MQ, your table might look like this:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">CREATE</span> <span style="color: #993333; font-weight: bold;">TABLE</span> <span style="color: #ff0000;">`msecs`</span> <span style="color: #66cc66;">&#40;</span>
  <span style="color: #ff0000;">`put_datetime`</span> datetime <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`put_msecs`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`get_datetime`</span> datetime <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span><span style="color: #66cc66;">,</span>
  <span style="color: #ff0000;">`get_msecs`</span> int<span style="color: #66cc66;">&#40;</span><span style="color: #cc66cc;">11</span><span style="color: #66cc66;">&#41;</span> <span style="color: #993333; font-weight: bold;">DEFAULT</span> <span style="color: #993333; font-weight: bold;">NULL</span>
<span style="color: #66cc66;">&#41;</span> ENGINE<span style="color: #66cc66;">=</span>InnoDB <span style="color: #993333; font-weight: bold;">DEFAULT</span> CHARSET<span style="color: #66cc66;">=</span>latin1;</pre></div></div>

<p>So in this table I am storing the datetime component in its native MySQL format and the millisecond component as an integer. Here are some examples:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2009/01/datetime_mysql.png' title='datetime msecs mysql'><img src='http://90kts.com/blog/wp-content/uploads/2009/01/datetime_mysql.png' alt='datetime msecs mysql' /></a></p>
<p>Now to retrieve and compare the values, I get the difference using TIME_TO_SEC for the datetime component, multiply it by 1000 to convert to milliseconds then add to the difference of the milliseconds component using basic maths:</p>

<div class="wp_syntax"><div class="code"><pre class="sql" style="font-family:monospace;"><span style="color: #993333; font-weight: bold;">SELECT</span> <span style="color: #66cc66;">&#40;</span><span style="color: #66cc66;">&#40;</span>TIME_TO_SEC<span style="color: #66cc66;">&#40;</span>get_datetime<span style="color: #66cc66;">&#41;</span> <span style="color: #66cc66;">-</span> TIME_TO_SEC<span style="color: #66cc66;">&#40;</span>put_datetime<span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">&#41;</span><span style="color: #66cc66;">*</span><span style="color: #cc66cc;">1000</span><span style="color: #66cc66;">&#41;</span>
<span style="color: #66cc66;">+</span> <span style="color: #66cc66;">&#40;</span>get_msecs<span style="color: #66cc66;">-</span>put_msecs<span style="color: #66cc66;">&#41;</span>
<span style="color: #993333; font-weight: bold;">AS</span> diff_msecs
<span style="color: #993333; font-weight: bold;">FROM</span> msecs</pre></div></div>

<p>That gives you difference in milliseconds for the demo table along these lines:<br />
2300<br />
1700<br />
300<br />
600700<br />
700</p>
<p>Hopefully that makes sense. Pipe up if you have an easier solution!</p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2009/storing-milliseconds-in-mysql/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Establishing Mysql DB Connectivity from Ruby</title>
		<link>http://altentee.com/2008/establishing-mysql-db-connectivity-from-ruby/</link>
		<comments>http://altentee.com/2008/establishing-mysql-db-connectivity-from-ruby/#comments</comments>
		<pubDate>Thu, 03 Jul 2008 01:27:49 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2008/establishing-mysql-db-connectivity-from-ruby/</guid>
		<description><![CDATA[<p>If you are a rails fan you will probably recommend using active record instead, but if you just want to hack away at your mysql db from within your Ruby code, you may find this handy&#8230;</p>
<p>I&#8217;m currently using a wamp box to serve up content for performance metrics. What I needed was a Ruby script [...]]]></description>
			<content:encoded><![CDATA[<p>If you are a rails fan you will probably recommend using active record instead, but if you just want to hack away at your mysql db from within your Ruby code, you may find this handy&#8230;</p>
<p>I&#8217;m currently using a <strong><a href="http://en.wikipedia.org/wiki/WAMP">wamp</a></strong> box to serve up content for performance metrics. What I needed was a Ruby script which could interrogate data on this installation.</p>
<p>You can download the binary required for this from <a href="http://rubyforge.org/projects/mysql-win">here</a>. After you install the gem (I do this off-line as my command prompt doesn&#8217;t allow me internet access here at work) you may find that you get an error similar to the following:<br />
<code>"NameError: uninitialized constant Mysql"</code></p>
<p>See what&#8217;s happening?<br />
<span id="more-166"></span><br />
To find out what&#8217;s happening, you can jump into an irb terminal and type the following:<br />
<code>irb(main):002:0> require 'mysql'</code></p>
<p>When you do you will probably get a popup dialog like this:<br />
<a href='http://90kts.com/blog/wp-content/uploads/2008/07/error_dll.jpg' title='error dll mysql'><img src='http://90kts.com/blog/wp-content/uploads/2008/07/error_dll.jpg' alt='error dll mysql' /></a></p>
<p>Basically if you read the README that comes with the gem you will notice:</p>
<blockquote><p> Dependencies &#8230;<br />
For this to work, you must have libmysql.dll in your PATH environmental variable. If you have MySQL installed locally, just make sure that <mysql_install_dir>\bin is in your path. If you don&#8217;t have MySQL installed locally, you can install one or more of the MySQL tools, find the libmysql.dll included in their bin directory, and copy it to the %SystemRoot%\System32 folder.</p></blockquote>
<p>So all you need to do is find out where your <strong>libmysql.dll</strong> lives:<br />
<code>D:\wamp>dir /b /s LIBMYSQL.dll<br />
D:\wamp\bin\apache\apache2.2.8\bin\libmysql.dll<br />
D:\wamp\bin\mysql\mysql5.0.51a\bin\libmySQL.dll<br />
D:\wamp\bin\php\php5.2.5\libmysql.dll</code></p>
<p>And then add that bin directory to your environment path:<br />
<code>D:\wamp\bin\mysql\mysql5.0.51a\bin</code></p>
<p>Hope that saves some of you some time in getting connectivity on your windows boxes!<br />
Attached below is some sample code to test your config.</p>

<div class="wp_syntax"><table><tr><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
</pre></td><td class="code"><pre class="ruby" style="font-family:monospace;"><span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'rubygems'</span>
<span style="color:#CC0066; font-weight:bold;">require</span> <span style="color:#996600;">'mysql'</span>
&nbsp;
<span style="color:#9966CC; font-weight:bold;">def</span> with_db
    dbh = Mysql.<span style="color:#9900CC;">real_connect</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'localhost'</span>, <span style="color:#996600;">'myuser'</span>, <span style="color:#996600;">'mypass'</span>, <span style="color:#996600;">'mydb'</span>, <span style="color:#006666;">3306</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    <span style="color:#9966CC; font-weight:bold;">begin</span>
        <span style="color:#9966CC; font-weight:bold;">yield</span> dbh
    <span style="color:#9966CC; font-weight:bold;">ensure</span>
        dbh.<span style="color:#9900CC;">close</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span>
&nbsp;
with_db <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>db<span style="color:#006600; font-weight:bold;">|</span>
    res = db.<span style="color:#9900CC;">query</span><span style="color:#006600; font-weight:bold;">&#40;</span><span style="color:#996600;">'select * from tablename'</span><span style="color:#006600; font-weight:bold;">&#41;</span>
    res.<span style="color:#9900CC;">each</span> <span style="color:#9966CC; font-weight:bold;">do</span> <span style="color:#006600; font-weight:bold;">|</span>row<span style="color:#006600; font-weight:bold;">|</span>
        <span style="color:#CC0066; font-weight:bold;">puts</span> row<span style="color:#006600; font-weight:bold;">&#91;</span><span style="color:#006666;">1</span><span style="color:#006600; font-weight:bold;">&#93;</span>
    <span style="color:#9966CC; font-weight:bold;">end</span>
<span style="color:#9966CC; font-weight:bold;">end</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2008/establishing-mysql-db-connectivity-from-ruby/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>An Alternative for Mercury Virtual Table Server</title>
		<link>http://altentee.com/2008/an-alternative-for-mercury-virtual-table-server/</link>
		<comments>http://altentee.com/2008/an-alternative-for-mercury-virtual-table-server/#comments</comments>
		<pubDate>Thu, 03 Apr 2008 05:10:13 +0000</pubDate>
		<dc:creator>Tim Koopmans</dc:creator>
				<category><![CDATA[90kts]]></category>
		<category><![CDATA[Altentee]]></category>
		<category><![CDATA[loadrunner]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[tools]]></category>

		<guid isPermaLink="false">http://90kts.com/blog/2008/an-alternative-for-mercury-virtual-table-server/</guid>
		<description><![CDATA[<p>Mercury&#8217;s Virtual Table Server (VTS) provides the following functionality when sharing data between vusers in your typical LoadRunner scenario &#8230;</p>
<p>Virtual Table Server (VTS) first edition, introduced the capability for LoadRunner virtual users, WinRunner and XRunner, to communicate in real time. Data extraction and communication was simplified but limited to column/queue level operations. The new Virtual [...]]]></description>
			<content:encoded><![CDATA[<p>Mercury&#8217;s Virtual Table Server (VTS) provides the following functionality when sharing data between vusers in your typical LoadRunner scenario &#8230;</p>
<blockquote><p>Virtual Table Server (VTS) first edition, introduced the capability for LoadRunner virtual users, WinRunner and XRunner, to communicate in real time. Data extraction and communication was simplified but limited to column/queue level operations. The new Virtual Table Server II provides a higher degree of data manipulation and 5-10 times better performance. From row level queries, retrievals, updates, insertions, unqueue entries, to database access, VTS II provides the functionality and ease for enhanced inter-process, inter-virtual user communication</p></blockquote>
<p>A useful tool in itself, but with some annoying limitations. <a href="http://www.myloadtest.com/mercury-virtual-table-server/">MyLoadTest</a> elaborates on this:</p>
<blockquote><p>The API is simple, but unfortunately does not allow you to write SQL queries; instead you must use the functions provided, like lrvtc_retrieve_row() and lrvtc_query_row()&#8230;</p></blockquote>
<p>Read on for an alternative when using web vusers in LoadRunner.<br />
<span id="more-127"></span></p>
<p>Using WAMP (Windows, Apache, MySql &#038; PHP) I came up with a simple alternative called VTSFaker. The concept relies on the use of web_reg_save parameters obtained from a simple web_url call to a &#8216;central&#8217; WAMP server. I say central in the sense you might have n load generators in your environment all sharing the single WAMP server.</p>
<p>In the LoadRunner script I have abstracted the call to the WAMP server using a custom dbApi() action which you can load in your vuser_init or include as a custom header.</p>
<p>In its simplest form, if you wanted to parametize a value called &#8216;advertiserId&#8217;, you simply need to call the dbApi function as follows:<br />
<code>dbApi("selectUniqueOnce", "advertiserId", "advertisers","","");</code></p>
<p>The purpose of the dbApi action is to call a web page hosted by your WAMP installation using query based parameters as follows:<br />
<code>http://d112295/VTSFaker/api.php?method=selectUniqueNext&#038;column=advertiserId&#038;table=advertisers&#038;vuser=None_-1_0&#038;value=&#038;where=</code></p>
<p>This in turn returns a formatted page with the result in a custom tag. LoadRunner then parametizes that result using a web_reg_save_param function call as follows:<br />
<code>web_reg_save_param(column,"LB=<span id=result>","RB=</span>","Search=Body","Notfound=warning",LAST);</code></p>
<p>All of this logic is abstracted in the dbApi action itself which hopefully simplifies the whole process.</p>
<p>In the background, I&#8217;ve created a simple API using PHP accessed via a webpage that makes calls to your MySql database. I think you get the picture &#8230; BTW, if you&#8217;re worried about performance, I did some preliminary tests on a 2GB RAM machine with the load generator and WAMP installation collocated with up to 600 concurrent vusers with no problems. Provided you index your MySql tables properly, result sets are returned in milliseconds, with not much fuss at all. In any case I&#8217;ve added an lr_start/end transaction statement to each API call, so that you could if necessary, subtract those average response times from your measured transactions if WAMP performance was degraded during your test run&#8230;</p>
<p>To get this all working follow the steps below:</p>
<p>1. Setup a WAMP installation. I&#8217;m using WAMPSERVER v2.0 which can be obtained for free at <a href="http://www.wampserver.com">http://www.wampserver.com</a></p>
<p>2. Setup your database tables; I&#8217;m assuming you know how to drive MySql. Here&#8217;s an example table I&#8217;m using at present:<br />
<code><br />
CREATE TABLE `advertisers` (<br />
  `id` int(4) NOT NULL auto_increment,<br />
  `advertiserId` varchar(64) default NULL,<br />
  `productId` varchar(64) default NULL,<br />
  `hasArtwork` tinyint(4) default NULL,<br />
  `vuserId` varchar(128) default NULL,<br />
  `update` timestamp NULL default NULL on update CURRENT_TIMESTAMP,<br />
  PRIMARY KEY  (`id`),<br />
  KEY `advertiserId_idx` (`advertiserId`)<br />
) ENGINE=InnoDB DEFAULT CHARSET=utf8;<br />
</code><br />
Note: the mandatory use of an id column (to help sort result sets) and a vuserId column (to provide unique result sets). The others are optional depending on what data you want to retrieve/store.</p>
<p>3. Setup your VTSFaker aliased website on WAMP (Apache -> Alias Directories -> Add an alias -> VTSFaker) using the example PHP files <a href='http://90kts.com/blog/wp-content/uploads/2008/04/vtsfaker.zip' title='VTSFaker'>here</a>.</p>
<p>4. Add to your vuser_init or custom header the dbApi action using the example code below.<br />
<code><br />
/*  ---------------------------------------------------------------------<br />
	Custom DB API for MySql</p>
<p>	Support for the following methods:<br />
		selectUniqueOnce -  select a new row that is unique for this vuser<br />
							and re-use row for entire scenario.<br />
		selectUniqueNext -  select next available row that is unique for<br />
							this vuser for entire scenario.<br />
		updateColumn	 -	Update a column based on where clause</p>
<p>	Examples:<br />
		char where[256];</p>
<p>		dbApi("selectUniqueOnce", 		// method<br />
			  "advertiserId", 			// column<br />
			  "advertisers","","");		// table</p>
<p>		dbApi("selectUniqueNext", 		// method<br />
			  "advertiserId", 			// column<br />
			  "advertisers","",""); 	// table</p>
<p>		strcpy(where, "");<br />
		strcat(where, "advertiserId=");<br />
		strcat(where, lr_eval_string("{advertiserId}") );</p>
<p>		dbApi("updateColumn",			// method<br />
			  "productId", 				// column<br />
			  "advertisers",			// table<br />
			  "123456",					// value<br />
			  where); 					// where<br />
	-------------------------------------------------------------------- */<br />
dbApi(char* method, char* column, char* table, char* value, char* where)<br />
{<br />
    // vars<br />
	int debug = 1;<br />
	int vuserId, scenarioId;<br />
	int httpRC;<br />
    char *vuserGroup;<br />
    char vuser[128];<br />
	char buff[20];<br />
    char url[256];</p>
<p>    // enum vuser<br />
    lr_whoami(&#038;vuserId, &#038;vuserGroup, &#038;scenarioId);<br />
    if(debug>0) lr_message( "Group: %s, vuser id: %d, scenario id %d", vuserGroup, vuserId, scenarioId);<br />
	strcpy(vuser, "");<br />
    strcat(vuser, vuserGroup);<br />
	sprintf(buff, "_%i", vuserId);<br />
	strcat(vuser, buff);<br />
	sprintf(buff, "_%i", scenarioId);<br />
	strcat(vuser, buff);</p>
<p>    // build url<br />
    strcpy(url,"URL=http://VTSFaker/VTSFaker/api.php?method=");<br />
    strcat(url,method);<br />
    strcat(url,"&#038;column=");<br />
    strcat(url,column);<br />
    strcat(url,"&#038;table=");<br />
    strcat(url,table);<br />
	strcat(url,"&#038;vuser=");<br />
    strcat(url,vuser);<br />
	strcat(url,"&#038;value=");<br />
	strcat(url,value);<br />
	strcat(url,"&#038;where=");<br />
	strcat(url,where);<br />
	if(debug>0) lr_message("dbAPI URL: %s", url);</p>
<p>    // get results<br />
	if (strncmp(method, "select", 6) == 0) {<br />
		web_reg_save_param(column,"LB=<span id=result>","RB=</span>","Search=Body","Notfound=warning",LAST);<br />
	}<br />
	lr_start_transaction("dbApi");<br />
	web_url("api.php",<br />
 		url,<br />
 		"Resource=0",<br />
 		"RecContentType=text/html",<br />
 		"Referer=",<br />
 		"Snapshot=t69.inf",<br />
 		"Mode=HTML",<br />
 		LAST);<br />
	lr_end_transaction("dbApi", LR_AUTO);</p>
<p>    // enum errors<br />
	httpRC = web_get_int_property(HTTP_INFO_RETURN_CODE);<br />
    if (httpRC != 200){<br />
 	   if (httpRC < 200){<br />
 		   lr_error_message("Error: HTTP Return Code %", httpRC);<br />
 	   }<br />
 	   else {<br />
 		   lr_error_message("Error: HTTP Return Code %i", httpRC);<br />
 	   }<br />
 	   return 1;<br />
 	}<br />
 	return 0;<br />
}<br />
</code></p>
<p>Enjoy <img src='http://altentee.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://altentee.com/2008/an-alternative-for-mercury-virtual-table-server/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
