<?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>Xaprb &#187; User Defined Functions</title>
	<atom:link href="http://www.xaprb.com/blog/tag/user-defined-functions/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.xaprb.com/blog</link>
	<description>Stay curious!</description>
	<lastBuildDate>Thu, 09 Feb 2012 10:55:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>How I built the NOW_USEC() UDF for MySQL</title>
		<link>http://www.xaprb.com/blog/2007/10/30/how-i-built-the-now_usec-udf-for-mysql/</link>
		<comments>http://www.xaprb.com/blog/2007/10/30/how-i-built-the-now_usec-udf-for-mysql/#comments</comments>
		<pubDate>Tue, 30 Oct 2007 12:57:50 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[amd64]]></category>
		<category><![CDATA[compiling]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[system time]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[User Defined Functions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/10/30/how-i-built-the-now_usec-udf-for-mysql/</guid>
		<description><![CDATA[<p>Last week I wrote about my efforts to <a href="http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/">measure MySQL's replication speed precisely</a>.  The most important ingredient in that recipe was the <a href="http://dev.mysql.com/doc/en/adding-functions.html">user-defined function</a> to get the system time with microsecond precision.  This post is about that function, which turned out to be surprisingly easy to write.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2005/12/01/windows-xps-built-in-unzipping-functionality-is-not-trustworthy/' rel='bookmark' title='Permanent Link: Windows XP&#8217;s built-in unzipping functionality is not trustworthy'>Windows XP&#8217;s built-in unzipping functionality is not trustworthy</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/' rel='bookmark' title='Permanent Link: How fast is MySQL replication?'>How fast is MySQL replication?</a></li>
<li><a href='http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/' rel='bookmark' title='Permanent Link: How to number rows in MySQL'>How to number rows in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2007/01/25/how-to-calculate-table-checksums-in-mysql/' rel='bookmark' title='Permanent Link: How to calculate table checksums in MySQL'>How to calculate table checksums in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2007/09/30/introducing-mysql-parallel-dump/' rel='bookmark' title='Permanent Link: Introducing MySQL Parallel Dump'>Introducing MySQL Parallel Dump</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Last week I wrote about my efforts to <a href="http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/">measure MySQL&#8217;s replication speed precisely</a>.  The most important ingredient in that recipe was the <a href="http://dev.mysql.com/doc/en/adding-functions.html">user-defined function</a> to get the system time with microsecond precision.  This post is about that function, which turned out to be surprisingly easy to write.</p>

<p>The <a href="http://dev.mysql.com/doc/en/adding-functions.html">manual section on user-defined functions</a> provides very good instructions on how they work and how to build them.  But just for the record, on Ubuntu 7.04 on an AMD64 machine, all I had to do was install the libmysqlclient15-dev package, and I was then able to compile the UDF with no further ado.  Also for the record, <a href="http://bugs.mysql.com/bug.php?id=28456">MySQL header files have some dependencies they shouldn&#8217;t</a> that break building against a downloaded tarball.  So don&#8217;t be surprised if you have troubles building against anything but Ubuntu&#8217;s provided header files.</p>

<p>Here&#8217;s the source, which I basically cribbed from a NOW_MSEC() function I saw in a bug report somewhere.  Really, there&#8217;s not much to it besides the basic skeleton of a UDF, with a few lines to actually get the system time.  And I actually believe if I took another ten minutes to learn about strftime(), there&#8217;s probably no need to do it in two steps; I could probably do the whole thing with one strftime() call and save a little memory and time.  But that&#8217;s what I get for copying and pasting code of unknown quality:</p>

<pre>#include &lt;my_global.h&gt;
#include &lt;my_sys.h&gt;
#include &lt;mysql.h&gt;

#include &lt;stdio.h&gt;
#include &lt;sys/time.h&gt;
#include &lt;time.h&gt;
#include &lt;unistd.h&gt;

extern "C" {
   my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
   char *now_usec(
               UDF_INIT *initid,
               UDF_ARGS *args,
               char *result,
               unsigned long *length, char *is_null, char *error);
}

my_bool now_usec_init(UDF_INIT *initid, UDF_ARGS *args, char *message) {
   return 0;
}

char *now_usec(UDF_INIT *initid, UDF_ARGS *args, char *result,
               unsigned long *length, char *is_null, char *error) {

  struct timeval tv;
  struct tm* ptm;
  char time_string[20]; /* e.g. "2006-04-27 17:10:52" */
  char *usec_time_string = result;
  time_t t;

  /* Obtain the time of day, and convert it to a tm struct. */
  gettimeofday (&amp;tv, NULL);
  t = (time_t)tv.tv_sec;
  ptm = localtime (&amp;t);   

  /* Format the date and time, down to a single second.  */
  strftime (time_string, sizeof (time_string), "%Y-%m-%d %H:%M:%S", ptm);

  /* Print the formatted time, in seconds, followed by a decimal point
 *      and the microseconds.  */
  sprintf(usec_time_string, "%s.%06ld\n", time_string, tv.tv_usec);

  *length = 26;

  return(usec_time_string);
}
</pre>

<p>The installation looks like this:</p>

<pre>baron@tigger now_usec $ make
gcc -fPIC -Wall -I/usr/include/mysql -shared -o now_usec.so now_usec.cc
baron@tigger now_usec $ sudo cp now_usec.so /lib
baron@tigger now_usec $ mysql test
mysql> create function now_usec returns string soname 'now_usec.so';
Query OK, 0 rows affected (0.00 sec)

mysql> select now_usec();
+----------------------------+
| now_usec()                 |
+----------------------------+
| 2007-10-23 10:28:13.862116 | 
+----------------------------+</pre>

<p>For those who have reached this page via Google searches and are looking for more information, you should check out the <a href="http://www.xcdsql.org/MySQL/UDF/">MySQL User Defined Function Library</a> project.  Lots of good UDFs there.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2005/12/01/windows-xps-built-in-unzipping-functionality-is-not-trustworthy/' rel='bookmark' title='Permanent Link: Windows XP&#8217;s built-in unzipping functionality is not trustworthy'>Windows XP&#8217;s built-in unzipping functionality is not trustworthy</a></li>
<li><a href='http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/' rel='bookmark' title='Permanent Link: How fast is MySQL replication?'>How fast is MySQL replication?</a></li>
<li><a href='http://www.xaprb.com/blog/2006/12/02/how-to-number-rows-in-mysql/' rel='bookmark' title='Permanent Link: How to number rows in MySQL'>How to number rows in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2007/01/25/how-to-calculate-table-checksums-in-mysql/' rel='bookmark' title='Permanent Link: How to calculate table checksums in MySQL'>How to calculate table checksums in MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2007/09/30/introducing-mysql-parallel-dump/' rel='bookmark' title='Permanent Link: Introducing MySQL Parallel Dump'>Introducing MySQL Parallel Dump</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/10/30/how-i-built-the-now_usec-udf-for-mysql/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>How fast is MySQL replication?</title>
		<link>http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/</link>
		<comments>http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/#comments</comments>
		<pubDate>Wed, 24 Oct 2007 02:00:48 +0000</pubDate>
		<dc:creator>Xaprb</dc:creator>
				<category><![CDATA[Federated storage engine]]></category>
		<category><![CDATA[Giuseppe Maxia]]></category>
		<category><![CDATA[logging]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[MySQL slave lag]]></category>
		<category><![CDATA[polling]]></category>
		<category><![CDATA[replication]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[User Defined Functions]]></category>

		<guid isPermaLink="false">http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/</guid>
		<description><![CDATA[<p>Very fast, as it turns out.  Click through to the full article for details.</p>


<strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/11/08/how-mysql-replication-got-out-of-sync/' rel='bookmark' title='Permanent Link: How MySQL replication got out of sync'>How MySQL replication got out of sync</a></li>
<li><a href='http://www.xaprb.com/blog/2008/02/29/how-to-sync-tables-in-master-master-mysql-replication/' rel='bookmark' title='Permanent Link: How to sync tables in master-master MySQL replication'>How to sync tables in master-master MySQL replication</a></li>
<li><a href='http://www.xaprb.com/blog/2007/05/12/how-fast-is-mysql-table-checksum/' rel='bookmark' title='Permanent Link: How fast is MySQL Table Checksum?'>How fast is MySQL Table Checksum?</a></li>
<li><a href='http://www.xaprb.com/blog/2008/03/09/a-very-fast-fnv-hash-function-for-mysql/' rel='bookmark' title='Permanent Link: A very fast FNV hash function for MySQL'>A very fast FNV hash function for MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2008/01/13/how-pre-fetching-relay-logs-speeds-up-mysql-replication-slaves/' rel='bookmark' title='Permanent Link: How pre-fetching relay logs speeds up MySQL replication slaves'>How pre-fetching relay logs speeds up MySQL replication slaves</a></li>
</ul>]]></description>
			<content:encoded><![CDATA[<p>Very fast, as it turns out.</p>

<p>While writing the chapter on replication for the upcoming second edition of High Performance MySQL, I decided to do a little test and measure replication speed more accurately than I&#8217;ve seen others do before.  The first edition of the book measured replication speed by inserting on the master and polling on the slave.  <a href="http://datacharmer.blogspot.com/2006/04/measuring-replication-speed.html">Giuseppe Maxia later followed up on that by improving the polling process</a>, and found events typically replicated within a half a millisecond.</p>

<p>Polling can only get you so far; the extra overhead caused by polling skews the measurements (even if you <a href="http://www.xaprb.com/blog/2006/05/04/how-to-make-a-program-choose-an-optimal-polling-interval/">poll smartly</a>).  I wanted to see if I could do this without polling the slave for results.  It turned out to be easier than I thought it would be.</p>

<p>All I had to do was write a <a href="http://dev.mysql.com/doc/en/adding-functions.html">MySQL User-Defined Function</a> that returns the system time to microsecond precision.  I&#8217;ll write another post about that later; in this post I want to talk about the results.</p>

<h3>The setup</h3>

<p>After writing and installing the function, I tested it.  Note that it&#8217;s non-deterministic, so you get different results even when you call it twice in the same query:</p>

<pre>SELECT NOW_USEC(), NOW_USEC(); 
+----------------------------+----------------------------+ 
| NOW_USEC()                 | NOW_USEC()                 | 
+----------------------------+----------------------------+ 
| 2007-10-23 10:41:10.743917 | 2007-10-23 10:41:10.743934 | 
+----------------------------+----------------------------+ </pre>

<p>The rest is easy.  I set up two MySQL instances on the same server (because there&#8217;s no way the clocks on two separate machines will be synced to the microsecond), and made one of them the master of the other.  On the master,</p>

<pre>CREATE TABLE test.lag_test( 
   id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
   now_usec VARCHAR(26) NOT NULL 
 ); 

INSERT INTO test.lag_test(now_usec) VALUES( NOW_USEC() ); </pre>

<h3>The results</h3>

<p>Now all that remains is to compare the difference from the slave and the master.  A Federated table is an easy way to do this.  On the slave:</p>

<pre>CREATE TABLE test.master_val ( 
   id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
   now_usec VARCHAR(26) NOT NULL 
) ENGINE=FEDERATED 
   CONNECTION='mysql://user:pass@127.0.0.1/test/lag_test'; </pre>

<p>A simple join and the TIMESTAMPDIFF function can now show the microseconds of lag between the time the query executed on the master and the slave:</p>

<pre>SELECT m.id, TIMESTAMPDIFF(FRAC_SECOND, m.now_usec, s.now_usec) AS usec_lag
FROM test.lag_test as s
   INNER JOIN test.master_val AS m USING(id); 
+----+----------+ 
| id | usec_lag | 
+----+----------+ 
|  1 |      476 | 
+----+----------+ </pre>

<p>I inserted a thousand rows into the master with a simple Perl script, with a 10-millisecond delay between rows to keep help the master and slave instances from fighting each other for CPU time. I then built a temporary table with the lag of each event, and grouped the results by lag time, to see what the most frequent lag times are:</p>

<pre>SELECT ROUND(lag / 1000000.0, 4) * 1000 AS msec_lag, COUNT(*)
FROM lag
GROUP BY msec_lag
ORDER BY msec_lag;
+----------+----------+ 
| msec_lag | COUNT(*) | 
+----------+----------+ 
|   0.1000 |      392 | 
|   0.2000 |      468 | 
|   0.3000 |       75 | 
|   0.4000 |       32 | 
|   0.5000 |       15 | 
|   0.6000 |        9 | 
|   0.7000 |        2 | 
|   1.3000 |        2 | 
|   1.4000 |        1 | 
|   1.8000 |        1 | 
|   4.6000 |        1 | 
|   6.6000 |        1 | 
|  24.3000 |        1 | 
+----------+----------+</pre>

<p>Not all that bad, eh?  It looks to me like MySQL can replicate most small queries in <em>200 to 300 microseconds</em>(!!!).  Of course, the speed is bounded by a) how long it takes to transfer the binary log event across the network and b) how fast the query executes.  In this case, both are very fast, showing that MySQL doesn&#8217;t add much overhead of its own to the replication process.</p>

<p>If anyone knows of a way to measure the delay between the event being logged in the master&#8217;s binary log, and the event being logged in the slave&#8217;s relay log, I&#8217;d be interested in seeing the results.  I&#8217;m guessing it&#8217;s practically instantaneous for small events like this, and most of the lag is in reading, parsing, and executing the SQL.</p>

<p><strong>Further Reading:</strong><ul><li><a href='http://www.xaprb.com/blog/2007/11/08/how-mysql-replication-got-out-of-sync/' rel='bookmark' title='Permanent Link: How MySQL replication got out of sync'>How MySQL replication got out of sync</a></li>
<li><a href='http://www.xaprb.com/blog/2008/02/29/how-to-sync-tables-in-master-master-mysql-replication/' rel='bookmark' title='Permanent Link: How to sync tables in master-master MySQL replication'>How to sync tables in master-master MySQL replication</a></li>
<li><a href='http://www.xaprb.com/blog/2007/05/12/how-fast-is-mysql-table-checksum/' rel='bookmark' title='Permanent Link: How fast is MySQL Table Checksum?'>How fast is MySQL Table Checksum?</a></li>
<li><a href='http://www.xaprb.com/blog/2008/03/09/a-very-fast-fnv-hash-function-for-mysql/' rel='bookmark' title='Permanent Link: A very fast FNV hash function for MySQL'>A very fast FNV hash function for MySQL</a></li>
<li><a href='http://www.xaprb.com/blog/2008/01/13/how-pre-fetching-relay-logs-speeds-up-mysql-replication-slaves/' rel='bookmark' title='Permanent Link: How pre-fetching relay logs speeds up MySQL replication slaves'>How pre-fetching relay logs speeds up MySQL replication slaves</a></li>
</ul>]]></content:encoded>
			<wfw:commentRss>http://www.xaprb.com/blog/2007/10/23/how-fast-is-mysql-replication/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
	</channel>
</rss>

