<?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>PlanetMysql.ru - информация о СУБД MySQL &#187; usability</title>
	<atom:link href="http://planetmysql.ru/category/usability/feed/" rel="self" type="application/rss+xml" />
	<link>http://planetmysql.ru</link>
	<description>Блог о самой популярной СУБД MySQL</description>
	<lastBuildDate>Wed, 08 Feb 2012 18:38:50 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Testing new builds with MySQL-Sandbox 3.0.24</title>
		<link>http://datacharmer.blogspot.com/2011/12/testing-new-builds-with-mysql-sandbox.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=testing-new-builds-with-mysql-sandbox-3-0-24</link>
		<comments>http://datacharmer.blogspot.com/2011/12/testing-new-builds-with-mysql-sandbox.html#comments</comments>
		<pubDate>Mon, 19 Dec 2011 14:53:00 +0000</pubDate>
		<dc:creator>Giuseppe Maxia</dc:creator>
				<category><![CDATA[MariaDB]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[percona]]></category>
		<category><![CDATA[recipes]]></category>
		<category><![CDATA[Replication]]></category>
		<category><![CDATA[sandbox]]></category>
		<category><![CDATA[tungsten]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://planetmysql.ru/?guid=1f084e3d7f0d3ef7e102417f25dfae27</guid>
		<description><![CDATA[MySQL::Sandbox 3.0.24 was released yesterday, with many new features.  More than vanilla MySQLIf you have missed my previous announcement, here's the gist of it. MySQL Sandbox can now deal with tarballs from either Percona Server or MariaDB.  The main difference after this change is that you can now create a directory called &#60;PREFIX&#62;5.5.16 and make_sandbox will recognize it as well as the plain 5.5.16.   $ make_sandbox --export_binaries --add_prefix=ps \   Percona-Server-5.5.11-rel20.2-114.Darwin.i386.tar.gz  \   -- --sandbox_directory=msb_ps5_5_11unpacking Percona-Server-5.5.11-rel20.2-114.Darwin.i386.tar.gz[…]installing with the following parameters:upper_directory                = /Users/gmax/sandboxessandbox_directory              = msb_ps5_5_11[…]basedir                        = $HOME/opt/mysql/ps5.5.11tmpdir                         = […]Your sandbox server was installed in $HOME/sandboxes/msb_ps5_5_11After the binary export, subsequent installations will be easier:  $ make_sandbox ps5.5.11The same commands can be used for MariaDB. At the moment, make_sandbox does not recognize other packages, but adding them should not be a big deal, provided that such packages look like MySQL. It wouldn't work with Drizzle, because it lacks the main ingredients for MySQL installation.  High Performance sandboxesWhile testing parallel replication and prefetch slaves with Tungsten Replicator, I realized that I was doing too much manual fiddling with my scripts. Since I need more performant servers, I added the basic items that I need to modify to enable a faster server. Now, using the '--high_performance' option with make_sandbox, you get a server that is much better than out-of-the-box MySQL. To avoid problems with too much RAM, I am using a default of 512 MB for InnoDB, which is not enough for really demanding tests, but at least it is a good placeholder in the sandbox configuration file, should you need to modify it.  $ make_sandbox 5.1.60 -- --high_performance[…]innodb-flush-method=O_DIRECT ; \innodb-log-file-size=50M ; \innodb_buffer_pool_size=512M ; \max_allowed_packet=48M ; \max-connections=350 ; \innodb-additional-mem-pool-size=50M ; \innodb-log-buffer-size=50M ; sync_binlog=0 ; \innodb-thread-concurrency=0 ; log-error=msandbox.err[…]Standalone masters and slavesMySQL Sandbox has had the ability of creating replicated systems for years. Yet, sometimes you need a stand-alone master server that you want to use for some odd experiment. Similarly, you may want to create a slave of a specific master without having a full replication system.  One case where you would like this ability is when you want to try replicating between servers of different versions.   $ make_sandbox 5.1.57 -- --master[…]my_clause                      = server-id=5157 ; log-bin=mysql-bin ; log-error=msandbox.err[…]Your sandbox server was installed in $HOME/sandboxes/msb_5_1_57$ make_sandbox 5.5.10 -- --slaveof='master_port=5157' […]my_clause                      = server-id=5510 ; log-bin=mysql-bin ; log-error=msandbox.err[…]Your sandbox server was installed in $HOME/sandboxes/msb_5_5_10$ ~/sandboxes/msb_5_1_57/use -e 'show master status'+------------------+----------+--------------+------------------+&#124; File             &#124; Position &#124; Binlog_Do_DB &#124; Binlog_Ignore_DB &#124;+------------------+----------+--------------+------------------+&#124; mysql-bin.000001 &#124;      106 &#124;              &#124;                  &#124;+------------------+----------+--------------+------------------+$ ~/sandboxes/msb_5_5_10/use -e 'show slave status\G'*************************** 1. row ***************************               Slave_IO_State: Waiting for master to send event                  Master_Host: 127.0.0.1                  Master_User: rsandbox                  Master_Port: 5157                Connect_Retry: 60              Master_Log_File: mysql-bin.000001          Read_Master_Log_Pos: 106               Relay_Log_File: mysql_sandbox5510-relay-bin.000002                Relay_Log_Pos: 252        Relay_Master_Log_File: mysql-bin.000001             Slave_IO_Running: Yes            Slave_SQL_Running: Yes              Replicate_Do_DB:           Replicate_Ignore_DB:            Replicate_Do_Table:        Replicate_Ignore_Table:       Replicate_Wild_Do_Table:   Replicate_Wild_Ignore_Table:                    Last_Errno: 0                   Last_Error:                  Skip_Counter: 0          Exec_Master_Log_Pos: 106              Relay_Log_Space: 420              Until_Condition: None               Until_Log_File:                 Until_Log_Pos: 0           Master_SSL_Allowed: No           Master_SSL_CA_File:            Master_SSL_CA_Path:               Master_SSL_Cert:             Master_SSL_Cipher:                Master_SSL_Key:         Seconds_Behind_Master: 0Master_SSL_Verify_Server_Cert: No                Last_IO_Errno: 0                Last_IO_Error:                Last_SQL_Errno: 0               Last_SQL_Error:   Replicate_Ignore_Server_Ids:              Master_Server_Id: 5157You can download MySQL::Sandbox from either launchpad or CPAN.]]></description>
			<content:encoded><![CDATA[<a href="http://mysqlsandbox.net">MySQL::Sandbox</a> 3.0.24 was released yesterday, with many <a href="http://mysqlsandbox.net/news.html">new features</a>.  <h3>More than vanilla MySQL</h3>If you have missed my previous announcement, here's the gist of it. MySQL Sandbox can now deal with tarballs from either <a href="http://www.percona.com/software/percona-server/">Percona Server</a> or <a href="http://downloads.askmonty.org/mariadb/">MariaDB</a>.  The main difference after this change is that you can now create a directory called &lt;PREFIX&gt;5.5.16 and make_sandbox will recognize it as well as the plain 5.5.16.   <pre>$ <b>make_sandbox --export_binaries --add_prefix=ps \<br />   Percona-Server-5.5.11-rel20.2-114.Darwin.i386.tar.gz  \<br />   -- --sandbox_directory=msb_ps5_5_11</b><br />unpacking Percona-Server-5.5.11-rel20.2-114.Darwin.i386.tar.gz<br />[…]<br />installing with the following parameters:<br />upper_directory                = /Users/gmax/sandboxes<br />sandbox_directory              = msb_ps5_5_11<br />[…]<br />basedir                        = $HOME/opt/mysql/ps5.5.11<br />tmpdir                         = <br />[…]<br />Your sandbox server was installed in $HOME/sandboxes/msb_ps5_5_11<br /></pre>After the binary export, subsequent installations will be easier:  <pre>$ <b>make_sandbox ps5.5.11</b><br /></pre>The same commands can be used for MariaDB. At the moment, make_sandbox does not recognize other packages, but adding them should not be a big deal, provided that such packages look like MySQL. It wouldn't work with Drizzle, because it lacks the main ingredients for MySQL installation.  <h3>High Performance sandboxes</h3>While testing parallel replication and prefetch slaves with <a href="http://tungsten-replicator.org">Tungsten Replicator</a>, I realized that I was doing too much manual fiddling with my scripts. Since I need more performant servers, I added the basic items that I need to modify to enable a faster server. Now, using the '--high_performance' option with make_sandbox, you get a server that is much better than out-of-the-box MySQL. To avoid problems with too much RAM, I am using a default of 512 MB for InnoDB, which is not enough for really demanding tests, but at least it is a good placeholder in the sandbox configuration file, should you need to modify it.  <pre>$ <b>make_sandbox 5.1.60 -- --high_performance</b><br />[…]<br />innodb-flush-method=O_DIRECT ; \<br />innodb-log-file-size=50M ; \<br />innodb_buffer_pool_size=512M ; \<br />max_allowed_packet=48M ; \<br />max-connections=350 ; \<br />innodb-additional-mem-pool-size=50M ; \<br />innodb-log-buffer-size=50M ; sync_binlog=0 ; \<br />innodb-thread-concurrency=0 ; log-error=msandbox.err<br />[…]<br /></pre><h3>Standalone masters and slaves</h3>MySQL Sandbox has had the ability of creating replicated systems for years. Yet, sometimes you need a stand-alone master server that you want to use for some odd experiment. Similarly, you may want to create a slave of a specific master without having a full replication system.  One case where you would like this ability is when you want to try <b>replicating between servers of different versions</b>.   <pre>$ <b>make_sandbox 5.1.57 -- --master</b><br />[…]<br />my_clause                      = server-id=5157 ; log-bin=mysql-bin ; log-error=msandbox.err<br />[…]<br />Your sandbox server was installed in $HOME/sandboxes/msb_5_1_57<br /><br />$ <b>make_sandbox 5.5.10 -- --slaveof='master_port=5157' </b><br />[…]<br />my_clause                      = server-id=5510 ; log-bin=mysql-bin ; log-error=msandbox.err<br />[…]<br />Your sandbox server was installed in $HOME/sandboxes/msb_5_5_10<br /><br /><br />$ <b>~/sandboxes/msb_5_1_57/use -e 'show master status'</b><br />+------------------+----------+--------------+------------------+<br />| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB |<br />+------------------+----------+--------------+------------------+<br />| mysql-bin.000001 |      106 |              |                  |<br />+------------------+----------+--------------+------------------+<br /><br />$ <b>~/sandboxes/msb_5_5_10/use -e 'show slave status\G'</b><br />*************************** 1. row ***************************<br />               Slave_IO_State: Waiting for master to send event<br />                  Master_Host: 127.0.0.1<br />                  Master_User: rsandbox<br />                  Master_Port: 5157<br />                Connect_Retry: 60<br />              Master_Log_File: mysql-bin.000001<br />          Read_Master_Log_Pos: 106<br />               Relay_Log_File: mysql_sandbox5510-relay-bin.000002<br />                Relay_Log_Pos: 252<br />        Relay_Master_Log_File: mysql-bin.000001<br />             Slave_IO_Running: Yes<br />            Slave_SQL_Running: Yes<br />              Replicate_Do_DB: <br />          Replicate_Ignore_DB: <br />           Replicate_Do_Table: <br />       Replicate_Ignore_Table: <br />      Replicate_Wild_Do_Table: <br />  Replicate_Wild_Ignore_Table: <br />                   Last_Errno: 0<br />                   Last_Error: <br />                 Skip_Counter: 0<br />          Exec_Master_Log_Pos: 106<br />              Relay_Log_Space: 420<br />              Until_Condition: None<br />               Until_Log_File: <br />                Until_Log_Pos: 0<br />           Master_SSL_Allowed: No<br />           Master_SSL_CA_File: <br />           Master_SSL_CA_Path: <br />              Master_SSL_Cert: <br />            Master_SSL_Cipher: <br />               Master_SSL_Key: <br />        Seconds_Behind_Master: 0<br />Master_SSL_Verify_Server_Cert: No<br />                Last_IO_Errno: 0<br />                Last_IO_Error: <br />               Last_SQL_Errno: 0<br />               Last_SQL_Error: <br />  Replicate_Ignore_Server_Ids: <br />             Master_Server_Id: 5157<br /></pre>You can download MySQL::Sandbox from either <a href="http://launchpad.net/mysql-sandbox/+download">launchpad</a> or <a href="http://search.cpan.org/perldoc?MySQL::Sandbox">CPAN</a>.<div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/16959946-6231639687718385832?l=datacharmer.blogspot.com" alt="" /></div><br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=31360&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=31360&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2011/12/19/testing-new-builds-with-mysql-sandbox-3-0-24/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Upgrading Tungsten Replicator: as easy as &#8230;</title>
		<link>http://datacharmer.blogspot.com/2011/09/upgrading-tungsten-replicator-as-easy.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=upgrading-tungsten-replicator-as-easy-as</link>
		<comments>http://datacharmer.blogspot.com/2011/09/upgrading-tungsten-replicator-as-easy.html#comments</comments>
		<pubDate>Thu, 22 Sep 2011 20:37:24 +0000</pubDate>
		<dc:creator>Giuseppe Maxia</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[recipes]]></category>
		<category><![CDATA[Replication]]></category>
		<category><![CDATA[tungsten]]></category>
		<category><![CDATA[update]]></category>
		<category><![CDATA[upgrade]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://planetmysql.ru/?guid=449a4f89583c5eeaca8362b3f5fe04af</guid>
		<description><![CDATA[When I talked about the usability improvements of Tungsten Replicator, I did not mention the procedure for upgrading.I was reminded about it by a question in the TR mailing list, and since the question was very relevant, I updated the Tungsten Cookbook with some quick upgrading instructions.A quick upgrading procedure is as important as the installer. Since we release software quite often, either because we have scheduled features to release or because of bug fixes, users want to apply a new release to an existing installation without much fuss. You can do the upgrade with a very quick and painless procedure.Let's suppose that you have installed one Tungsten Replicator cluster using this command:## using tungsten-replicator 2.0.4#TUNGSTEN_HOME=/home/tungsten/installs/master_slave./tools/tungsten-installer \  --master-slave \  --master-host=r1 \  --datasource-user=tungsten \  --datasource-password=secret \  --service-name=dragon \  --home-directory=$TUNGSTEN_HOME \  --cluster-hosts=r1,r2,r3,r4 \  --start-and-reportIf you want to upgrade to the very latest Tungsten Replicator 2.0.5, build 321, this is what you need to do. Get the latest tarball, and expand it;Stop the replicator;Run the update command (this will also restart the replicator)Check that the replicator is running again.The actual upgrade command is in bold in the following script.## using tungsten-replicator 2.0.5-321 (get it from bit.ly/tr20_builds) #TUNGSTEN_HOME=/home/tungsten/installs/master_slaveHOSTS=(r1 r2 r3 r4)for HOST in ${HOSTS[*]} do    ssh $HOST $TUNGSTEN_HOME/tungsten/tungsten-replicator/bin/replicator stop    ./tools/update --host=$HOST --user=tungsten --release-directory=$TUNGSTEN_HOME -q    $$TUNGSTEN_HOME/tungsten/tungsten-replicator/bin/trepctl -host $HOST servicesdoneOne benefit of this procedure, in addition to being brief and effective, is that the previous binaries are preserved.Before the upgrade, you will see:$ ls -lh ~/installs/master_slave/ ~/installs/master_slave/releases/home/tungsten/installs/master_slave/:total 32Kdrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 backupsdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 configsdrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 relaydrwxrwxr-x 4 tungsten tungsten 4.0K Sep 22 22:06 releasesdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 service-logsdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 sharedrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 thllrwxrwxrwx 1 tungsten tungsten   75 Sep 22 22:06 tungsten -&#62; /home/tungsten/installs/master_slave/releases/tungsten-replicator-2.0.4/home/tungsten/installs/master_slave/releases:total 8.0Kdrwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:03 tungsten-replicator-2.0.4The 'tungsten' directory is a symlink to the actual binaries inside the 'releases' directory.After the upgrade, the same directory looks like this:ls -lh ~/installs/master_slave/ ~/installs/master_slave/releases/home/tungsten/installs/master_slave/:total 32Kdrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 backupsdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 configsdrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 relaydrwxrwxr-x 4 tungsten tungsten 4.0K Sep 22 22:06 releasesdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 service-logsdrwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 sharedrwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 thllrwxrwxrwx 1 tungsten tungsten   75 Sep 22 22:06 tungsten -&#62; /home/tungsten/installs/master_slave/releases/tungsten-replicator-2.0.5-321/home/tungsten/installs/master_slave/releases:total 8.0Kdrwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:03 tungsten-replicator-2.0.4drwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:06 tungsten-replicator-2.0.5-321If you did some manual change to the files in 2.0.4, you will be able to retrieve them. Upgrading from earlier versions of Tungsten Replicator is not as smooth. Since we changed the installation format,  it has become incompatible from previous versions. Clusters running TR 2.0.3 need to be reinstalled manually. The next upgrade, though, will be much faster!]]></description>
			<content:encoded><![CDATA[When I talked about the usability improvements of Tungsten Replicator, I did not mention the procedure for upgrading.I was reminded about it by a question in the TR mailing list, and since the question was very relevant, I updated the Tungsten Cookbook with some quick <a href="http://code.google.com/p/tungsten-replicator/wiki/TungstenReplicatorCookbook#Upgrading_from_Tungsten_Replicator_2.0.4_to_2.0.5">upgrading instructions</a>.A quick upgrading procedure is as important as the installer. Since we release software quite often, either because we have scheduled features to release or because of bug fixes, users want to apply a new release to an existing installation without much fuss. You can do the upgrade with a very quick and painless procedure.Let's suppose that you have installed one Tungsten Replicator cluster using this command:<pre><br />#<br /># using tungsten-replicator 2.0.4<br />#<br />TUNGSTEN_HOME=/home/tungsten/installs/master_slave<br />./tools/tungsten-installer \<br />  --master-slave \<br />  --master-host=r1 \<br />  --datasource-user=tungsten \<br />  --datasource-password=secret \<br />  --service-name=dragon \<br />  --home-directory=$TUNGSTEN_HOME \<br />  --cluster-hosts=r1,r2,r3,r4 \<br />  --start-and-report<br /></pre>If you want to upgrade to the very latest Tungsten Replicator 2.0.5, build 321, this is what you need to do. <ul><li>Get the latest tarball, and expand it;</li><li>Stop the replicator;</li><li>Run the update command (this will also restart the replicator)</li><li>Check that the replicator is running again.</li></ul>The actual upgrade command is in bold in the following script.<pre><br />#<br /># using tungsten-replicator 2.0.5-321 (get it from <a href="http://bit.ly/tr20_builds">bit.ly/tr20_builds</a>) <br />#<br />TUNGSTEN_HOME=/home/tungsten/installs/master_slave<br />HOSTS=(r1 r2 r3 r4)<br />for HOST in ${HOSTS[*]} <br />do <br />   ssh $HOST $TUNGSTEN_HOME/tungsten/tungsten-replicator/bin/replicator stop <br />   <b>./tools/update --host=$HOST --user=tungsten --release-directory=$TUNGSTEN_HOME -q </b><br />   $$TUNGSTEN_HOME/tungsten/tungsten-replicator/bin/trepctl -host $HOST services<br />done<br /></pre>One benefit of this procedure, in addition to being brief and effective, is that the previous binaries are preserved.Before the upgrade, you will see:<pre><br />$ ls -lh ~/installs/master_slave/ ~/installs/master_slave/releases<br />/home/tungsten/installs/master_slave/:<br />total 32K<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 backups<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 configs<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 relay<br />drwxrwxr-x 4 tungsten tungsten 4.0K Sep 22 22:06 releases<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 service-logs<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 share<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 thl<br />lrwxrwxrwx 1 tungsten tungsten   75 Sep 22 22:06 tungsten -> <b>/home/tungsten/installs/master_slave/releases/tungsten-replicator-2.0.4</b><br />/home/tungsten/installs/master_slave/releases:<br />total 8.0K<br />drwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:03 tungsten-replicator-2.0.4<br /></pre>The 'tungsten' directory is a symlink to the actual binaries inside the 'releases' directory.After the upgrade, the same directory looks like this:<pre><br />ls -lh ~/installs/master_slave/ ~/installs/master_slave/releases<br />/home/tungsten/installs/master_slave/:<br />total 32K<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 backups<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 configs<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 relay<br />drwxrwxr-x 4 tungsten tungsten 4.0K Sep 22 22:06 releases<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 service-logs<br />drwxrwxr-x 2 tungsten tungsten 4.0K Sep 22 22:03 share<br />drwxrwxr-x 3 tungsten tungsten 4.0K Sep 22 22:03 thl<br />lrwxrwxrwx 1 tungsten tungsten   75 Sep 22 22:06 tungsten -> <b>/home/tungsten/installs/master_slave/releases/tungsten-replicator-2.0.5-321</b><br /><br />/home/tungsten/installs/master_slave/releases:<br />total 8.0K<br />drwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:03 tungsten-replicator-2.0.4<br />drwxr-xr-x 6 tungsten tungsten 4.0K Sep 22 22:06 tungsten-replicator-2.0.5-321<br /></pre>If you did some manual change to the files in 2.0.4, you will be able to retrieve them. Upgrading from earlier versions of Tungsten Replicator is not as smooth. Since we changed the installation format,  it has become incompatible from previous versions. Clusters running TR 2.0.3 need to be reinstalled manually. The next upgrade, though, will be much faster!<div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/16959946-1234122059737251337?l=datacharmer.blogspot.com" alt="" /></div><br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=30056&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=30056&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2011/09/23/upgrading-tungsten-replicator-as-easy-as/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Usability improvements in Tungsten Replicator 2.0.4</title>
		<link>http://datacharmer.blogspot.com/2011/08/usability-improvements-in-tungsten-204.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=usability-improvements-in-tungsten-replicator-2-0-4</link>
		<comments>http://datacharmer.blogspot.com/2011/08/usability-improvements-in-tungsten-204.html#comments</comments>
		<pubDate>Thu, 11 Aug 2011 16:19:24 +0000</pubDate>
		<dc:creator>Giuseppe Maxia</dc:creator>
				<category><![CDATA[continuent]]></category>
		<category><![CDATA[innovation]]></category>
		<category><![CDATA[Installation]]></category>
		<category><![CDATA[logs]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[remote]]></category>
		<category><![CDATA[Replication]]></category>
		<category><![CDATA[tungsten]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://planetmysql.ru/?guid=5f3de847610d830c18dc3ebb2ec962ff</guid>
		<description><![CDATA[If you love a software product, you should try to improve it, and not be afraid of criticizing it.  This principle has guided me with MySQL (where I have submitted many usability bugs, and discussed interface with developers for years), and it proves true for Tungsten Replicator as well. When I started working at Continuent, while I was impressed by the technology, I found the installation procedure and the product logs quite discouraging. I would almost say disturbing. Fortunately, my colleagues have agreed on my usability focus, and we can enjoy some tangible improvements. I have already mentioned the new installation procedure, which requires just one command to install a full master/slave cluster.  I would like to show how you can use the new installer to deploy a multiple source replication topology like the following:    The first step is to install one master in each node. I can run the commands from node #4, which is the one that will eventually receive the updates from the remote masters, and where I need to install the slave services:  TUNGSTEN_BASE=$HOME/newinst
SERVICES=(alpha bravo charlie delta)
REPLICATOR=$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/replicator

for N in 1 2 3 4
do
    INDEX=$(($N-1))

  ./tools/tungsten-installer \
    --master-slave \
    --master-host=qa.r$N.continuent.com \
    --datasource-user=tungsten \
    --datasource-password=secret \
    --service-name=${SERVICES[$INDEX]} \
    --home-directory=$TUNGSTEN_BASE \
    --cluster-hosts=qa.r$N.continuent.com \
    --start-and-report
done
The above loop will install a master (remotely or locally) in the four servers.  Then I need to create the slave services. To do it, I use the updated configure-service in the tools directory.  TUNGSTEN_TOOLS=$TUNGSTEN_BASE/tungsten/tools
COMMON_OPTIONS='-C -q 
    --local-service-name=delta 
    --role=slave 
    --service-type=remote 
    --allow-bidi-unsafe=true 
    --datasource=qa_r4_continuent_com' 

$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r1.continuent.com  alpha 
$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r2.continuent.com  bravo
$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r3.continuent.com  charlie 

$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/replicator restart
$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/trepctl services
These commands create the slave services locally in Delta. After restarting the replicator, a simple test will be creating something different in each master, and check that the data has replicated to the single slave.  The latest improvement in matter of usability is the simplification of the replicator logs. Until a few days ago, if you had an error in the replicator, you would get a long list of not exactly helpful stuff. For example, if I create a table in a slave, and then create the same table in the master, I will break replication. The extended log would produce something like this:  INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,216 [tsandbox - q-to-dbms-0] ERROR pipeline.SingleThreadStageTask Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,217 [tsandbox - Event dispatcher thread] ERROR management.OpenReplicatorManager Received error notification, shutting down services: Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; com.continuent.tungsten.replicator.applier.ApplierException: java.sql.SQLException: Statement failed on slave but succeeded on master
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:183)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.applier.JdbcApplier.apply(JdbcApplier.java:1233)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.applier.ApplierWrapper.apply(ApplierWrapper.java:101)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.pipeline.SingleThreadStageTask.runTask(SingleThreadStageTask.java:498)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.pipeline.SingleThreadStageTask.run(SingleThreadStageTask.java:155)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at java.lang.Thread.run(Unknown Source)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; Caused by: java.sql.SQLException: Statement failed on slave but succeeded on master
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:139)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       ... 5 more
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; Caused by: java.sql.SQLSyntaxErrorException: Table 't1' already exists
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at org.drizzle.jdbc.internal.SQLExceptionMapper.get(SQLExceptionMapper.java:78)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at org.drizzle.jdbc.DrizzleStatement.executeBatch(DrizzleStatement.java:930)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:125)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       ... 5 more
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; Caused by: org.drizzle.jdbc.internal.common.QueryException: Table 't1' already exists
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at org.drizzle.jdbc.internal.mysql.MySQLProtocol.executeQuery(MySQLProtocol.java:500)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at org.drizzle.jdbc.internal.mysql.MySQLProtocol.executeBatch(MySQLProtocol.java:546)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       at org.drizzle.jdbc.DrizzleStatement.executeBatch(DrizzleStatement.java:917)
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124;       ... 6 more
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,218 [tsandbox - Event dispatcher thread] WARN  management.OpenReplicatorManager Performing emergency service shutdown
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,219 [tsandbox - Event dispatcher thread] INFO  pipeline.Pipeline Shutting down pipeline: slave
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,219 [tsandbox - q-to-dbms-0] INFO  pipeline.SingleThreadStageTask Terminating processing for stage task thread
INFO   &#124; jvm 1    &#124; 2011/08/11 18:10:52 &#124; 2011-08-11 18:10:52,219 [tsandbox - q-to-dbms-0] INFO  pipeline.SingleThreadStageTask Last successfully processed event prior to termination: seqno=0 eventid=mysql-bin.000002:0000000000000426;20
Did you see the reason for the error? No? Neither did I. I would need to open the THL, look for event #1, and determine what it was.  Instead, the new user.log looks like this: 2011-08-11 18:10:52,216 ERROR Received error notification: Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
Caused by : java.sql.SQLException: Statement failed on slave but succeeded on master
Caused by : Statement failed on slave but succeeded on master
Caused by : Table 't1' already exists
Caused by : Table 't1' already exists
2011-08-11 18:10:54,721 INFO  State changed ONLINE -&#62; OFFLINE:ERROR
2011-08-11 18:10:54,721 WARN  Received irrelevant event for current state: state=OFFLINE:ERROR event=OfflineNotification
That's much better. It is not perfect yet, but it will be soon. Right now, it tells me what is wrong without forcing me to go hunting for it amid hundreds of stack trace lines.  Give it a try, using the latest replicator build.]]></description>
			<content:encoded><![CDATA[If you love a software product, you should try to improve it, and not be afraid of criticizing it.  This principle has guided me with MySQL (where I have submitted many usability bugs, and discussed interface with developers for years), and it proves true for <a href="http://tungsten-replicator.org">Tungsten Replicator</a> as well. When I started working at Continuent, while I was impressed by the technology, I found the installation procedure and the product logs quite discouraging. I would almost say disturbing. Fortunately, my colleagues have agreed on my usability focus, and we can enjoy some tangible improvements. I have already mentioned the <a href="http://datacharmer.blogspot.com/2011/06/getting-started-with-tungsten.html">new installation procedure</a>, which requires just one command to install a full master/slave cluster.  I would like to show how you can use the new installer to deploy a multiple source replication topology like the following:  <img src="https://lh6.googleusercontent.com/_gVfZHGgf5LA/TXO04pRkW0I/AAAAAAAABEE/Ws3-Py7RMdE/Tungsten_multi_source_replication.png" width="500" title="Multiple source replication" />  The first step is to install one master in each node. I can run the commands from node #4, which is the one that will eventually receive the updates from the remote masters, and where I need to install the slave services:  <pre>TUNGSTEN_BASE=$HOME/newinst
<br />SERVICES=(alpha bravo charlie delta)
<br />REPLICATOR=$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/replicator
<br />
<br />for N in 1 2 3 4
<br />do
<br />    INDEX=$(($N-1))
<br />
<br />  ./tools/tungsten-installer \
<br />    --master-slave \
<br />    --master-host=qa.r$N.continuent.com \
<br />    --datasource-user=tungsten \
<br />    --datasource-password=secret \
<br />    --service-name=${SERVICES[$INDEX]} \
<br />    --home-directory=$TUNGSTEN_BASE \
<br />    --cluster-hosts=qa.r$N.continuent.com \
<br />    --start-and-report
<br />done
<br /></pre>The above loop will install a master (remotely or locally) in the four servers.  Then I need to create the slave services. To do it, I use the updated <code>configure-service</code> in the <code>tools</code> directory.  <pre>TUNGSTEN_TOOLS=$TUNGSTEN_BASE/tungsten/tools
<br />COMMON_OPTIONS='-C -q 
<br />    --local-service-name=delta 
<br />    --role=slave 
<br />    --service-type=remote 
<br />    --allow-bidi-unsafe=true 
<br />    --datasource=qa_r4_continuent_com' 
<br />
<br />$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r1.continuent.com  alpha 
<br />$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r2.continuent.com  bravo
<br />$TUNGSTEN_TOOLS/configure-service $COMMON_OPTIONS --master-host=qa.r3.continuent.com  charlie 
<br />
<br />$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/replicator restart
<br />$TUNGSTEN_BASE/tungsten/tungsten-replicator/bin/trepctl services
<br /></pre>These commands create the slave services locally in Delta. After restarting the replicator, a simple test will be creating something different in each master, and check that the data has replicated to the single slave.  The latest improvement in matter of usability is the simplification of the replicator logs. Until a few days ago, if you had an error in the replicator, you would get a long list of not exactly helpful stuff. For example, if I create a table in a slave, and then create the same table in the master, I will break replication. The extended log would produce something like this:  <pre>INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,216 [tsandbox - q-to-dbms-0] ERROR pipeline.SingleThreadStageTask Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,217 [tsandbox - Event dispatcher thread] ERROR management.OpenReplicatorManager Received error notification, shutting down services: Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | com.continuent.tungsten.replicator.applier.ApplierException: java.sql.SQLException: Statement failed on slave but succeeded on master
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:183)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.applier.JdbcApplier.apply(JdbcApplier.java:1233)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.applier.ApplierWrapper.apply(ApplierWrapper.java:101)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.pipeline.SingleThreadStageTask.runTask(SingleThreadStageTask.java:498)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.pipeline.SingleThreadStageTask.run(SingleThreadStageTask.java:155)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at java.lang.Thread.run(Unknown Source)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | Caused by: java.sql.SQLException: Statement failed on slave but succeeded on master
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:139)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       ... 5 more
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | Caused by: java.sql.SQLSyntaxErrorException: Table 't1' already exists
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at org.drizzle.jdbc.internal.SQLExceptionMapper.get(SQLExceptionMapper.java:78)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at org.drizzle.jdbc.DrizzleStatement.executeBatch(DrizzleStatement.java:930)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at com.continuent.tungsten.replicator.applier.MySQLDrizzleApplier.applyStatementData(MySQLDrizzleApplier.java:125)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       ... 5 more
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | Caused by: org.drizzle.jdbc.internal.common.QueryException: Table 't1' already exists
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at org.drizzle.jdbc.internal.mysql.MySQLProtocol.executeQuery(MySQLProtocol.java:500)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at org.drizzle.jdbc.internal.mysql.MySQLProtocol.executeBatch(MySQLProtocol.java:546)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       at org.drizzle.jdbc.DrizzleStatement.executeBatch(DrizzleStatement.java:917)
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 |       ... 6 more
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,218 [tsandbox - Event dispatcher thread] WARN  management.OpenReplicatorManager Performing emergency service shutdown
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,219 [tsandbox - Event dispatcher thread] INFO  pipeline.Pipeline Shutting down pipeline: slave
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,219 [tsandbox - q-to-dbms-0] INFO  pipeline.SingleThreadStageTask Terminating processing for stage task thread
<br />INFO   | jvm 1    | 2011/08/11 18:10:52 | 2011-08-11 18:10:52,219 [tsandbox - q-to-dbms-0] INFO  pipeline.SingleThreadStageTask Last successfully processed event prior to termination: seqno=0 eventid=mysql-bin.000002:0000000000000426;20
<br /></pre>Did you see the reason for the error? No? Neither did I. I would need to open the THL, look for event #1, and determine what it was.  Instead, the new user.log looks like this: <pre>2011-08-11 18:10:52,216 ERROR Received error notification: Event application failed: seqno=1 fragno=0 message=java.sql.SQLException: Statement failed on slave but succeeded on master
<br />Caused by : java.sql.SQLException: Statement failed on slave but succeeded on master
<br />Caused by : Statement failed on slave but succeeded on master
<br />Caused by : Table 't1' already exists
<br />Caused by : Table 't1' already exists
<br />2011-08-11 18:10:54,721 INFO  State changed ONLINE -> OFFLINE:ERROR
<br />2011-08-11 18:10:54,721 WARN  Received irrelevant event for current state: state=OFFLINE:ERROR event=OfflineNotification
<br /></pre>That's much better. It is not perfect yet, but it will be soon. Right now, it tells me what is wrong without forcing me to go hunting for it amid hundreds of stack trace lines.  Give it a try, using the <a href="http://s3.amazonaws.com/files.continuent.com/builds/nightly/tungsten-2.0-snapshots/index.html">latest replicator build</a>. <div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/16959946-7937723470921980252?l=datacharmer.blogspot.com" alt="" /></div><br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=29675&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=29675&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2011/08/11/usability-improvements-in-tungsten-replicator-2-0-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Exchanging partitions with tables</title>
		<link>http://datacharmer.blogspot.com/2010/04/exchanging-partitions-with-tables.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=exchanging-partitions-with-tables</link>
		<comments>http://datacharmer.blogspot.com/2010/04/exchanging-partitions-with-tables.html#comments</comments>
		<pubDate>Thu, 29 Apr 2010 16:40:00 +0000</pubDate>
		<dc:creator>Giuseppe Maxia</dc:creator>
				<category><![CDATA[5.6]]></category>
		<category><![CDATA[dba]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[partitions]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[While I was presenting my partitioning tutorial at the latest MySQL Conference, I announced a new feature that was, as far as I knew, still in the planning stage. Mattias Jonsson, one of the partitions developers, was in attendance, and corrected me, explaining that the feature was actually available in a prototype. So, we can have a look at this improvement, which I am sure will make DBAs quite happy. The new feature is an instantaneous exchange between a partition and a table with the same structure. Using this feature, you can transfer the contents of one partition to one table, and vice versa. Since the transition is done only in the attribution of the data, there is no copy involved. The data stays where it is at the moment. What is in the table ends up in the partition and what's in the partition ends up in the table. Let's see an example. With the data in figure 1, where we have a partitioned table t1 and an empty table t2 with the same structure, we can issue the following statement:ALTER TABLE t1EXCHANGE PARTITION p2WITH TABLE t2 After the exchange, partition p2 is empty, and table t2 contains 4 records.If we repeat the command, the contents will be swapped again, leaving table t2 empty and partition p2 with its original contents.If you want to test on your own, you can get the code from Launchpad. Once you get the code, you can use cmake to build the server.$ cmake-gui .# add the options you need. For example, enable innodb # or else you will need to load it as a plugin.$ make &#38;&#38; ./scripts/make_binary_distributionYou can then use this script to test the new functionality. You may want to change Innodb with MyISAM to test it thoroughly. At the moment, it doesn't work with the archive engine (yet).# ############################# test_exchange_partitions.sql# ############################use test;set default_storage_engine=innodb;drop procedure if exists compare_tables;delimiter //create procedure compare_tables (wanted int)reads sql databegin    set @part_table     := (select count(*) from t1);    set @non_part_table := (select count(*) from t2);    select @part_table, @non_part_table,         if(@non_part_table = wanted, "OK", "error") as expected;end //delimiter ;drop table if exists t1, t2;create table t1 (i int) # not null primary key)partition by range (i)     (partition p01 values less than  (100001), partition p02 values less than  (200001), partition p03 values less than  (300001), partition p04 values less than  (400001), partition p05 values less than  (500001), partition p06 values less than  (600001), partition p07 values less than  (700001), partition p08 values less than  (800001), partition p09 values less than  (900001), partition p10 values less than (1000001), partition p11 values less than (maxvalue));create table t2 (i int ) ; # not null primary key);select table_name, engine from information_schema.tables where table_schema='test' and table_type='base table';select 'generating 1 million records. ...' as info;# generates 1 million records# see this article for details# http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.htmlcreate or replace view v3 as select null union all select null union all select null;create or replace view v10 as select null from v3 a, v3 b union all select null;create or replace view v1000 as select null from v10 a, v10 b, v10 c;set @n = 0;insert into t1 select @n:=@n+1 from v1000 a,v1000 b;select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test';call compare_tables(0);alter table t1 exchange partition p04 with table t2; call compare_tables(100000);select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test';alter table t1 exchange partition p04 with table t2; call compare_tables(0);alter table t1 exchange partition p04 with table t2; call compare_tables(100000);Here is a test run:$ ~/sandboxes/msb_5_6_99/use -t test -vvv &#60; test_exch_part.sql --------------set default_storage_engine=innodb--------------Query OK, 0 rows affected (0.00 sec)--------------drop procedure if exists compare_tables--------------Query OK, 0 rows affected (0.00 sec)--------------create procedure compare_tables (wanted int)reads sql databegin    set @part_table     := (select count(*) from t1);    set @non_part_table := (select count(*) from t2);    select @part_table, @non_part_table,         if(@non_part_table = wanted, "OK", "error") as expected;end--------------Query OK, 0 rows affected (0.00 sec)--------------drop table if exists t1, t2--------------Query OK, 0 rows affected (0.07 sec)--------------create table t1 (i int) partition by range (i)     (partition p01 values less than  (100001), partition p02 values less than  (200001), partition p03 values less than  (300001), partition p04 values less than  (400001), partition p05 values less than  (500001), partition p06 values less than  (600001), partition p07 values less than  (700001), partition p08 values less than  (800001), partition p09 values less than  (900001), partition p10 values less than (1000001), partition p11 values less than (maxvalue))--------------Query OK, 0 rows affected (0.08 sec)--------------create table t2 (i int )--------------Query OK, 0 rows affected (0.14 sec)--------------select table_name, engine from information_schema.tables where table_schema='test' and table_type='base table'--------------+------------+--------+&#124; table_name &#124; engine &#124;+------------+--------+&#124; t1         &#124; InnoDB &#124;&#124; t2         &#124; InnoDB &#124;+------------+--------+2 rows in set (0.01 sec)--------------select 'generating 1 million records. ...' as info--------------+-----------------------------------+&#124; info                              &#124;+-----------------------------------+&#124; generating 1 million records. ... &#124;+-----------------------------------+1 row in set (0.00 sec)--------------create or replace view v3 as select null union all select null union all select null--------------Query OK, 0 rows affected (0.12 sec)--------------create or replace view v10 as select null from v3 a, v3 b union all select null--------------Query OK, 0 rows affected (0.14 sec)--------------create or replace view v1000 as select null from v10 a, v10 b, v10 c--------------Query OK, 0 rows affected (0.09 sec)--------------set @n = 0--------------Query OK, 0 rows affected (0.00 sec)--------------insert into t1 select @n:=@n+1 from v1000 a,v1000 b--------------Query OK, 1000000 rows affected (10.01 sec)Records: 1000000  Duplicates: 0  Warnings: 0--------------select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test'--------------+----------------+------------+&#124; partition_name &#124; table_rows &#124;+----------------+------------+&#124; p01            &#124;     100623 &#124;&#124; p02            &#124;     100623 &#124;&#124; p03            &#124;     100623 &#124;&#124; p04            &#124;     100623 &#124;&#124; p05            &#124;     100623 &#124;&#124; p06            &#124;     100623 &#124;&#124; p07            &#124;     100623 &#124;&#124; p08            &#124;     100623 &#124;&#124; p09            &#124;     100623 &#124;&#124; p10            &#124;     100623 &#124;&#124; p11            &#124;          0 &#124;+----------------+------------+11 rows in set (0.01 sec)--------------call compare_tables(0)--------------+-------------+-----------------+----------+&#124; @part_table &#124; @non_part_table &#124; expected &#124;+-------------+-----------------+----------+&#124;     1000000 &#124;               0 &#124; OK       &#124;+-------------+-----------------+----------+1 row in set (0.56 sec)Query OK, 0 rows affected (0.56 sec)--------------alter table t1 exchange partition p04 with table t2--------------Query OK, 0 rows affected (0.01 sec)--------------call compare_tables(100000)--------------+-------------+-----------------+----------+&#124; @part_table &#124; @non_part_table &#124; expected &#124;+-------------+-----------------+----------+&#124;      900000 &#124;          100000 &#124; OK       &#124;+-------------+-----------------+----------+1 row in set (0.54 sec)Query OK, 0 rows affected (0.54 sec)--------------select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test'--------------+----------------+------------+&#124; partition_name &#124; table_rows &#124;+----------------+------------+&#124; p01            &#124;     100623 &#124;&#124; p02            &#124;     100623 &#124;&#124; p03            &#124;     100623 &#124;&#124; p04            &#124;          0 &#124;&#124; p05            &#124;     100623 &#124;&#124; p06            &#124;     100623 &#124;&#124; p07            &#124;     100623 &#124;&#124; p08            &#124;     100623 &#124;&#124; p09            &#124;     100623 &#124;&#124; p10            &#124;      91799 &#124;&#124; p11            &#124;          0 &#124;+----------------+------------+11 rows in set (0.01 sec)--------------alter table t1 exchange partition p04 with table t2--------------Query OK, 0 rows affected (0.05 sec)--------------call compare_tables(0)--------------+-------------+-----------------+----------+&#124; @part_table &#124; @non_part_table &#124; expected &#124;+-------------+-----------------+----------+&#124;     1000000 &#124;               0 &#124; OK       &#124;+-------------+-----------------+----------+1 row in set (0.56 sec)Query OK, 0 rows affected (0.56 sec)--------------alter table t1 exchange partition p04 with table t2--------------Query OK, 0 rows affected (0.00 sec)--------------call compare_tables(100000)--------------+-------------+-----------------+----------+&#124; @part_table &#124; @non_part_table &#124; expected &#124;+-------------+-----------------+----------+&#124;      900000 &#124;          100000 &#124; OK       &#124;+-------------+-----------------+----------+1 row in set (0.56 sec)Query OK, 0 rows affected (0.56 sec)ByeNotice that the value for "table_rows" is only approximate with InnoDB, while it is reliable for MyISAM. Anyway, when it says that a partition has 0 records, it's reliable for any engine. Here you see that, after the exchange, partition  p04 is empty.The exchange is repeated twice, to make sure that it works both ways.Notice also that, if the table contains data that doesn't fit with the partition, the server throws an error, and the exchange does not happen.mysql &#62; insert into t2 values (2000000);Query OK, 1 row affected (0.00 sec)mysql &#62; alter table t1 exchange partition p04 with table t2;ERROR 1697 (HY000): Found row that does not match the partitionIf you remove the offending row from the table, the exchange works as expected.]]></description>
			<content:encoded><![CDATA[<table border="0"><tr><td><a href="http://datacharmer.blogspot.com/"><img src="http://lh4.ggpht.com/_gVfZHGgf5LA/S9mgr9RD2YI/AAAAAAAAA3o/qro7xTepnTo/mysql_partitions.png" alt="MySQL Partitions" title="MySQL Partitions" width="250" border="0" /></a></td><td>While I was presenting my partitioning tutorial at the latest MySQL Conference, I announced a new feature that was, as far as I knew, still in the planning stage. Mattias Jonsson, one of the partitions developers, was in attendance, and corrected me, explaining that the feature was actually available in a prototype. </td></tr></table><br />So, we can have a look at this improvement, which I am sure will make DBAs quite happy. The new feature is an <a href="http://forge.mysql.com/worklog/task.php?id=4445">instantaneous exchange between a partition and a table</a> with the same structure. Using this feature, you can transfer the contents of one partition to one table, and vice versa. Since the transition is done only in the attribution of the data, there is no copy involved. The data stays where it is at the moment. What is in the table ends up in the partition and what's in the partition ends up in the table. Let's see an example.<br /><img src="http://lh5.ggpht.com/_gVfZHGgf5LA/S9mgrskJ-RI/AAAAAAAAA3g/2amf0u_n6FY/exchange_partition_before.png" border="1" /> <br />With the data in figure 1, where we have a partitioned table t1 and an empty table t2 with the same structure, we can issue the following statement:<br /><pre><code>ALTER TABLE t1<br />EXCHANGE PARTITION p2<br />WITH TABLE t2</code></pre><br /><img src="http://lh6.ggpht.com/_gVfZHGgf5LA/S9mgr1fxIcI/AAAAAAAAA3k/R_4WrM3FgQo/exchange_partition_after.png" border="1" /> <br />After the exchange, partition p2 is empty, and table t2 contains 4 records.<br />If we repeat the command, the contents will be swapped again, leaving table t2 empty and partition p2 with its original contents.<br /><br />If you want to test on your own, you can get the code from <a href="https://code.edge.launchpad.net/~mysql/mysql-server/mysql-next-mr-wl4445">Launchpad</a>. Once you get the code, you can use <a href="http://datacharmer.blogspot.com/2010/04/building-mysql-55-with-cmake.html">cmake to build the server</a>.<br /><pre><code><br />$ cmake-gui .<br /># add the options you need. For example, enable innodb <br /># or else you will need to load it as a plugin.<br />$ make && ./scripts/make_binary_distribution<br /></code></pre><br />You can then use this script to test the new functionality. You may want to change Innodb with MyISAM to test it thoroughly. At the moment, it doesn't work with the archive engine (yet).<br /><pre><code><br /># ############################<br /># test_exchange_partitions.sql<br /># ############################<br />use test;<br />set default_storage_engine=innodb;<br />drop procedure if exists compare_tables;<br />delimiter //<br />create procedure compare_tables (wanted int)<br />reads sql data<br />begin<br />    set @part_table     := (select count(*) from t1);<br />    set @non_part_table := (select count(*) from t2);<br />    select @part_table, @non_part_table, <br />        if(@non_part_table = wanted, "OK", "error") as expected;<br />end //<br />delimiter ;<br /><br />drop table if exists t1, t2;<br />create table t1 (i int) # not null primary key)<br />partition by range (i) <br />    (<br />partition p01 values less than  (100001), <br />partition p02 values less than  (200001), <br />partition p03 values less than  (300001), <br />partition p04 values less than  (400001), <br />partition p05 values less than  (500001), <br />partition p06 values less than  (600001), <br />partition p07 values less than  (700001), <br />partition p08 values less than  (800001), <br />partition p09 values less than  (900001), <br />partition p10 values less than (1000001), <br />partition p11 values less than (maxvalue));<br /><br />create table t2 (i int ) ; # not null primary key);<br /><br />select table_name, engine <br />from information_schema.tables <br />where table_schema='test' and table_type='base table';<br /><br /><br />select 'generating 1 million records. ...' as info;<br /># generates 1 million records<br /># see this article for details<br /># http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.html<br />create or replace view v3 as select null union all select null union all select null;<br />create or replace view v10 as select null from v3 a, v3 b union all select null;<br />create or replace view v1000 as select null from v10 a, v10 b, v10 c;<br />set @n = 0;<br />insert into t1 select @n:=@n+1 from v1000 a,v1000 b;<br /><br />select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test';<br /><br />call compare_tables(0);<br /><br />alter table t1 exchange partition p04 with table t2; <br />call compare_tables(100000);<br /><br />select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test';<br /><br />alter table t1 exchange partition p04 with table t2; <br />call compare_tables(0);<br /><br />alter table t1 exchange partition p04 with table t2; <br />call compare_tables(100000);<br /></code></pre><br />Here is a test run:<br /><pre><code><br />$ ~/sandboxes/msb_5_6_99/use -t test -vvv &lt; test_exch_part.sql <br />--------------<br />set default_storage_engine=innodb<br />--------------<br /><br />Query OK, 0 rows affected (0.00 sec)<br /><br />--------------<br />drop procedure if exists compare_tables<br />--------------<br /><br />Query OK, 0 rows affected (0.00 sec)<br /><br />--------------<br />create procedure compare_tables (wanted int)<br />reads sql data<br />begin<br />    set @part_table     := (select count(*) from t1);<br />    set @non_part_table := (select count(*) from t2);<br />    select @part_table, @non_part_table, <br />        if(@non_part_table = wanted, "OK", "error") as expected;<br />end<br />--------------<br /><br />Query OK, 0 rows affected (0.00 sec)<br /><br />--------------<br />drop table if exists t1, t2<br />--------------<br /><br />Query OK, 0 rows affected (0.07 sec)<br /><br />--------------<br />create table t1 (i int) <br />partition by range (i) <br />    (<br />partition p01 values less than  (100001), <br />partition p02 values less than  (200001), <br />partition p03 values less than  (300001), <br />partition p04 values less than  (400001), <br />partition p05 values less than  (500001), <br />partition p06 values less than  (600001), <br />partition p07 values less than  (700001), <br />partition p08 values less than  (800001), <br />partition p09 values less than  (900001), <br />partition p10 values less than (1000001), <br />partition p11 values less than (maxvalue))<br />--------------<br /><br />Query OK, 0 rows affected (0.08 sec)<br /><br />--------------<br />create table t2 (i int )<br />--------------<br /><br />Query OK, 0 rows affected (0.14 sec)<br /><br />--------------<br />select table_name, engine <br />from information_schema.tables <br />where table_schema='test' and table_type='base table'<br />--------------<br /><br />+------------+--------+<br />| table_name | engine |<br />+------------+--------+<br />| t1         | InnoDB |<br />| t2         | InnoDB |<br />+------------+--------+<br />2 rows in set (0.01 sec)<br /><br />--------------<br />select 'generating 1 million records. ...' as info<br />--------------<br /><br />+-----------------------------------+<br />| info                              |<br />+-----------------------------------+<br />| generating 1 million records. ... |<br />+-----------------------------------+<br />1 row in set (0.00 sec)<br /><br />--------------<br />create or replace view v3 as select null union all select null union all select null<br />--------------<br /><br />Query OK, 0 rows affected (0.12 sec)<br /><br />--------------<br />create or replace view v10 as select null from v3 a, v3 b union all select null<br />--------------<br /><br />Query OK, 0 rows affected (0.14 sec)<br /><br />--------------<br />create or replace view v1000 as select null from v10 a, v10 b, v10 c<br />--------------<br /><br />Query OK, 0 rows affected (0.09 sec)<br /><br />--------------<br />set @n = 0<br />--------------<br /><br />Query OK, 0 rows affected (0.00 sec)<br /><br />--------------<br />insert into t1 select @n:=@n+1 from v1000 a,v1000 b<br />--------------<br /><br />Query OK, 1000000 rows affected (10.01 sec)<br />Records: 1000000  Duplicates: 0  Warnings: 0<br /><br />--------------<br />select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test'<br />--------------<br /><br />+----------------+------------+<br />| partition_name | table_rows |<br />+----------------+------------+<br />| p01            |     100623 |<br />| p02            |     100623 |<br />| p03            |     100623 |<br />| p04            |     100623 |<br />| p05            |     100623 |<br />| p06            |     100623 |<br />| p07            |     100623 |<br />| p08            |     100623 |<br />| p09            |     100623 |<br />| p10            |     100623 |<br />| p11            |          0 |<br />+----------------+------------+<br />11 rows in set (0.01 sec)<br /><br />--------------<br />call compare_tables(0)<br />--------------<br /><br />+-------------+-----------------+----------+<br />| @part_table | @non_part_table | expected |<br />+-------------+-----------------+----------+<br />|     1000000 |               0 | OK       |<br />+-------------+-----------------+----------+<br />1 row in set (0.56 sec)<br /><br />Query OK, 0 rows affected (0.56 sec)<br /><br />--------------<br />alter table t1 exchange partition p04 with table t2<br />--------------<br /><br />Query OK, 0 rows affected (0.01 sec)<br /><br />--------------<br />call compare_tables(100000)<br />--------------<br /><br />+-------------+-----------------+----------+<br />| @part_table | @non_part_table | expected |<br />+-------------+-----------------+----------+<br />|      900000 |          100000 | OK       |<br />+-------------+-----------------+----------+<br />1 row in set (0.54 sec)<br /><br />Query OK, 0 rows affected (0.54 sec)<br /><br />--------------<br />select partition_name, table_rows from information_schema . partitions where table_name='t1' and table_schema='test'<br />--------------<br /><br />+----------------+------------+<br />| partition_name | table_rows |<br />+----------------+------------+<br />| p01            |     100623 |<br />| p02            |     100623 |<br />| p03            |     100623 |<br />| p04            |          0 |<br />| p05            |     100623 |<br />| p06            |     100623 |<br />| p07            |     100623 |<br />| p08            |     100623 |<br />| p09            |     100623 |<br />| p10            |      91799 |<br />| p11            |          0 |<br />+----------------+------------+<br />11 rows in set (0.01 sec)<br /><br />--------------<br />alter table t1 exchange partition p04 with table t2<br />--------------<br /><br />Query OK, 0 rows affected (0.05 sec)<br /><br />--------------<br />call compare_tables(0)<br />--------------<br /><br />+-------------+-----------------+----------+<br />| @part_table | @non_part_table | expected |<br />+-------------+-----------------+----------+<br />|     1000000 |               0 | OK       |<br />+-------------+-----------------+----------+<br />1 row in set (0.56 sec)<br /><br />Query OK, 0 rows affected (0.56 sec)<br /><br />--------------<br />alter table t1 exchange partition p04 with table t2<br />--------------<br /><br />Query OK, 0 rows affected (0.00 sec)<br /><br />--------------<br />call compare_tables(100000)<br />--------------<br /><br />+-------------+-----------------+----------+<br />| @part_table | @non_part_table | expected |<br />+-------------+-----------------+----------+<br />|      900000 |          100000 | OK       |<br />+-------------+-----------------+----------+<br />1 row in set (0.56 sec)<br /><br />Query OK, 0 rows affected (0.56 sec)<br /><br />Bye<br /></code></pre><br />Notice that the value for "table_rows" is only approximate with InnoDB, while it is reliable for MyISAM. Anyway, when it says that a partition has 0 records, it's reliable for any engine. Here you see that, after the exchange, partition  p04 is empty.<br />The exchange is repeated twice, to make sure that it works both ways.<br />Notice also that, if the table contains data that doesn't fit with the partition, the server throws an error, and the exchange does not happen.<br /><pre><code><br />mysql &gt; insert into t2 values (2000000);<br />Query OK, 1 row affected (0.00 sec)<br /><br />mysql &gt; alter table t1 exchange partition p04 with table t2;<br />ERROR 1697 (HY000): Found row that does not match the partition<br /></code></pre><br />If you remove the offending row from the table, the exchange works as expected.<div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/16959946-8561679074431929442?l=datacharmer.blogspot.com" alt="" /></div><br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=24558&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=24558&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2010/04/29/exchanging-partitions-with-tables/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Holiday gift &#8212; A deep look at MySQL 5.5 partitioning enhancements</title>
		<link>http://datacharmer.blogspot.com/2009/12/holiday-gift-deep-look-at-mysql-55.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=holiday-gift-a-deep-look-at-mysql-5-5-partitioning-enhancements</link>
		<comments>http://datacharmer.blogspot.com/2009/12/holiday-gift-deep-look-at-mysql-55.html#comments</comments>
		<pubDate>Thu, 24 Dec 2009 19:24:00 +0000</pubDate>
		<dc:creator>Giuseppe Maxia</dc:creator>
				<category><![CDATA[5.1]]></category>
		<category><![CDATA[5.5]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[partitioning]]></category>
		<category><![CDATA[partitions]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Half a day into my vacation, I managed to finish an article on a topic that has been intriguing me for a while. Since several colleagues were baffled by the semantics of the new enhancements of MySQL 5.5 partitions, after talking at length with the creator and the author of the manual pages, I produced this article: A deep look at MySQL 5.5 partitioning enhancements.Happy holidays!]]></description>
			<content:encoded><![CDATA[<table border="0"><tr><td><br /><a href="http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html"><img src="http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning/partitioning_placement_002.png" width="300" alt="A deep look at MySQL 5.5 partitioning enhancements" title="A deep look at MySQL 5.5 partitioning enhancements" border="0" /></a><br /></td><td><br />Half a day into my vacation, I managed to finish an article on a topic that has been intriguing me for a while. <br />Since several colleagues were baffled by the semantics of the new enhancements of MySQL 5.5 partitions, after talking at length with the creator and the author of the manual pages, I produced this article: <a href="http://dev.mysql.com/tech-resources/articles/mysql_55_partitioning.html">A deep look at MySQL 5.5 partitioning enhancements</a>.<br />Happy holidays!<br /></td></tr></table><div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/16959946-8463892460899345105?l=datacharmer.blogspot.com" alt="" /></div><br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=22793&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=22793&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2009/12/24/holiday-gift-a-deep-look-at-mysql-5-5-partitioning-enhancements/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Forums are crap. Can we get some help?</title>
		<link>http://brian.moonspot.net/forums-are-crap-help-us?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=forums-are-crap-can-we-get-some-help</link>
		<comments>http://brian.moonspot.net/forums-are-crap-help-us#comments</comments>
		<pubDate>Mon, 12 Oct 2009 17:01:44 +0000</pubDate>
		<dc:creator>Brian Moon</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[phorum]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false">http://brian.moonspot.net/forums-are-crap-help-us</guid>
		<description><![CDATA[Amy Hoy has written a blog post about why forums are crap.
And she is right. Forum software does not always do a good job of
helping people communicate. I have worked with Amy. She did a great
analysis of dealnews.com that
led to our new design. So, she is not to be ignored.

However, as a software developer (Phorum), I see a lot of problems and
no answers.&#160; And it is not all on the software.&#160; Web site
owners use forums to solve problems that they really, really suck
at.&#160; Ideally, every web site would be very unique for their
audience.&#160; They would use a custom solution that fits a number
of patterns that best solves their problem.&#160; However, most web
site owners don't want to take the time to do such things.&#160;
They want a one stop, drop in solution. See the monolith that is
vBulletin, scary.

And what if a forum is the best solution? Well, software
developers, in general, are not good designers. They don't think
like normal people. And they don't see their applications as a
whole, but as pieces that do jobs. The forum software market has
been run by software developers for over 10 years. Most of them all
are still copies of what UBB was 13 years
ago. And software (like Phorum) that has tried to be different is
shunned by the online communities of the world because they don't
work/look/feel like every other forum software on the planet.

So, as software developers, what are we to do? We want to make
great software. We want to help our users help their users. But,
what we have been doing for 10+ years has only been adequate. As
the leader of an open source forum software project, I am open to
any and all ideas.]]></description>
			<content:encoded><![CDATA[Amy Hoy has written a blog post about why <a href="http://sweatyd.posterous.com/forums-are-crap">forums are crap</a>.
And she is right. Forum software does not always do a good job of
helping people communicate. I have worked with Amy. She did a great
analysis of <a href="http://dealnews.com/">dealnews.com</a> that
led to our new design. So, she is not to be ignored.<br>
<br>
However, as a software developer (<a href="http://www.phorum.org/">Phorum</a>), I see a lot of problems and
no answers.&nbsp; And it is not all on the software.&nbsp; Web site
owners use forums to solve problems that they really, really suck
at.&nbsp; Ideally, every web site would be very unique for their
audience.&nbsp; They would use a custom solution that fits a number
of patterns that best solves their problem.&nbsp; However, most web
site owners don't want to take the time to do such things.&nbsp;
They want a one stop, drop in solution. See the monolith that is
vBulletin, scary.<br>
<br>
And what if a forum is the best solution? Well, software
developers, in general, are not good designers. They don't think
like normal people. And they don't see their applications as a
whole, but as pieces that do jobs. The forum software market has
been run by software developers for over 10 years. Most of them all
are still copies of what <a href="http://en.wikipedia.org/wiki/UBB.classic">UBB</a> was 13 years
ago. And software (like Phorum) that has tried to be different is
shunned by the online communities of the world because they don't
work/look/feel like every other forum software on the planet.<br>
<br>
So, as software developers, what are we to do? We want to make
great software. We want to help our users help their users. But,
what we have been doing for 10+ years has only been adequate. As
the leader of an open source forum software project, I am open to
any and all ideas.<br/>PlanetMySQL Voting:
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=21677&vote=1&apivote=1">Vote UP</a> /
	 <a href="http://planet.mysql.com/entry/vote/?entry_id=21677&vote=-1&apivote=1">Vote DOWN</a>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2009/10/12/forums-are-crap-can-we-get-some-help/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>OPTIMIZE TABLE on Cluster (revisited)</title>
		<link>http://johanandersson.blogspot.com/2009/08/optimize-table-on-cluster-revisited.html?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=optimize-table-on-cluster-revisited</link>
		<comments>http://johanandersson.blogspot.com/2009/08/optimize-table-on-cluster-revisited.html#comments</comments>
		<pubDate>Tue, 04 Aug 2009 12:53:00 +0000</pubDate>
		<dc:creator>Johan Andersson</dc:creator>
				<category><![CDATA[bugs]]></category>
		<category><![CDATA[memory management]]></category>
		<category><![CDATA[MySQL Cluster 7.0]]></category>
		<category><![CDATA[usability]]></category>

		<guid isPermaLink="false"></guid>
		<description><![CDATA[Jonas just wrote a patch to this bug on OPTIMIZE TABLE, and the issue that was also discussed in this blog post. Jonas also fixed this bug when he was at it.Before, OPTIMIZE TABLE hardly freed up any pages and to defragment you had to do a rolling restart of the data nodes. Now, there is only a 2% discrepancy between OPTIMIZE TABLE and doing a rolling restart. This is great stuff.This will fix will make it into 6.3.26 and 7.0.7.See below for details:Creating two tables, t5 and t6:CREATE TABLE `t5` (`id` varchar(32) CHARACTER SET utf8 NOT NULL,`name` varchar(32) NOT NULL DEFAULT '',`unit` int(11) DEFAULT NULL,PRIMARY KEY (`id`,`name`)) ENGINE=ndbcluster DEFAULT CHARSET=latin1And then the following table:'CREATE TABLE `t6` ( `id` varchar(32) CHARACTER SET utf8 NOT NULL, `name` varchar(32) NOT NULL DEFAULT '', c0 int unsigned not null, c1 int unsigned not null, data2 varchar(255),  `unit` int(11) DEFAULT NULL, PRIMARY KEY (`id`,`name`) ) ENGINE=ndbcluster DEFAULT CHARSET=latin1;Then we use hugoLoad (a test program that isn't built by default in the src distribution of cluster) to load it with 1M records../hugoLoad -r 1000000 -d test t5./hugoLoad -r 1000000 -d test t6Memory usage after population:Node 2: Data usage is 45%(14890 32K pages of total 32768)Node 2: Index usage is 22%(3722 8K pages of total 16416)Node 3: Data usage is 45%(14890 32K pages of total 32768)Node 3: Index usage is 22%(3722 8K pages of total 16416)Delete 500K records from t5.mysql&#62; set ndb_use_transactions=0;Query OK, 0 rows affected (0.00 sec)mysql&#62; delete from t5 limit 100000;Query OK, 100000 rows affected (2.73 sec)mysql&#62; delete from t5 limit 100000;Query OK, 100000 rows affected (3.13 sec)mysql&#62; delete from t5 limit 100000;Query OK, 100000 rows affected (3.11 sec)mysql&#62; delete from t5 limit 100000;Query OK, 100000 rows affected (3.13 sec)mysql&#62; delete from t5 limit 100000;Query OK, 100000 rows affected (2.97 sec)Memory usage after deletion:Node 2: Data usage is 45%(14890 32K pages of total 32768)Node 2: Index usage is 19%(3120 8K pages of total 16416)ndb_mgm&#62; Node 3: Data usage is 45%(14890 32K pages of total 32768)Node 3: Index usage is 19%(3121 8K pages of total 16416)Run OPTIMIZE TABLE:mysql&#62; optimize table t5;+---------+----------+----------+----------+&#124; Table   &#124; Op       &#124; Msg_type &#124; Msg_text &#124;+---------+----------+----------+----------+&#124; test.t5 &#124; optimize &#124; status   &#124; OK       &#124;+---------+----------+----------+----------+1 row in set (1 min 41.94 sec)CPU UTIL during OPTIMIZE TABLE:User:23.8%   Sys: 4.9%  ndbd               Memory usage after OPTIMIZE TABLE:                  ndb_mgm&#62; Node 2: Data usage is 39%(13090 32K pages of total 32768)Node 2: Index usage is 19%(3120 8K pages of total 16416)Node 3: Data usage is 39%(13090 32K pages of total 32768)Node 3: Index usage is 19%(3121 8K pages of total 16416)                                                                                Delete 500K (50%) of the records from t6:mysql&#62; set ndb_use_transactions=0;Query OK, 0 rows affected (0.00 sec)mysql&#62; delete from t6 limit 100000;Query OK, 100000 rows affected (2.77 sec)mysql&#62; delete from t6 limit 100000;Query OK, 100000 rows affected (3.05 sec)mysql&#62; delete from t6 limit 100000;Query OK, 100000 rows affected (3.12 sec)mysql&#62; delete from t6 limit 100000;Query OK, 100000 rows affected (3.19 sec)mysql&#62; delete from t6 limit 100000;Query OK, 100000 rows affected (3.24 sec)Memory usage after deletion:Node 2: Data usage is 39%(13090 32K pages of total 32768)Node 2: Index usage is 15%(2521 8K pages of total 16416)Node 3: Data usage is 39%(13090 32K pages of total 32768)Node 3: Index usage is 15%(2522 8K pages of total 16416)Run OPTIMIZE TABLE:mysql&#62; optimize table t6;+---------+----------+----------+----------+&#124; Table   &#124; Op       &#124; Msg_type &#124; Msg_text &#124;+---------+----------+----------+----------+&#124; test.t6 &#124; optimize &#124; status   &#124; OK       &#124;+---------+----------+----------+----------+1 row in set (1 min 45.83 sec)Memory usage after OPTIMIZE TABLE:Node 2: Data usage is 28%(9249 32K pages of total 32768)Node 2: Index usage is 15%(2521 8K pages of total 16416)Node 3: Data usage is 28%(9249 32K pages of total 32768)Node 3: Index usage is 15%(2522 8K pages of total 16416)After restart of node 3:Node 2: Data usage is 28%(9249 32K pages of total 32768)Node 2: Index usage is 15%(2521 8K pages of total 16416)Node 3: Data usage is 26%(8568 32K pages of total 32768)Node 3: Index usage is 13%(2236 8K pages of total 16416)Only two percent diff between rolling restart and OPTIMIZE TABLE. Excellent. Thank you Jonas for fixing this.]]></description>
			<content:encoded><![CDATA[Jonas just wrote a patch to this <a href="http://bugs.mysql.com/bug.php?id=43683">bug</a> on OPTIMIZE TABLE, and the issue that was also discussed in this <a href="http://johanandersson.blogspot.com/2009/03/memory-deallocationdefragmentation-and.html">blog post</a>. Jonas also fixed this <a href="http://bugs.mysql.com/bug.php?id=45971">bug</a> when he was at it.<br /><br />Before, <code>OPTIMIZE TABLE</code> hardly freed up any pages and to defragment you had to do a rolling restart of the data nodes. <br /><br />Now, there is only a <span>2%</span> discrepancy between <code>OPTIMIZE TABLE</code> and doing a rolling restart. This is great stuff.<br />This will fix will make it into <span>6.3.26 and 7.0.7</span>.<br /><br />See below for details:<br /><br />Creating two tables, t5 and t6:<br /><code><br />CREATE TABLE `t5` (<br />`id` varchar(32) CHARACTER SET utf8 NOT NULL,<br />`name` varchar(32) NOT NULL DEFAULT '',<br />`unit` int(11) DEFAULT NULL,<br />PRIMARY KEY (`id`,`name`)<br />) ENGINE=ndbcluster DEFAULT CHARSET=latin1<br /></code><br />And then the following table:<br /><code><br />'CREATE TABLE `t6` ( `id` varchar(32) CHARACTER SET utf8 NOT NULL, `name` varchar(32) NOT NULL DEFAULT '', c0 int unsigned not null, c1 int unsigned not null, data2 varchar(255),  `unit` int(11) DEFAULT NULL, PRIMARY KEY (`id`,`name`) ) ENGINE=ndbcluster DEFAULT CHARSET=latin1;<br /></code><br /><br />Then we use <code>hugoLoad</code> (a test program that isn't built by default in the src distribution of cluster) to load it with 1M records.<br /><code><br />./hugoLoad -r 1000000 -d test t5<br />./hugoLoad -r 1000000 -d test t6<br /></code><br /><br />Memory usage after population:<br /><code><br />Node 2: Data usage is 45%(14890 32K pages of total 32768)<br />Node 2: Index usage is 22%(3722 8K pages of total 16416)<br />Node 3: Data usage is 45%(14890 32K pages of total 32768)<br />Node 3: Index usage is 22%(3722 8K pages of total 16416)<br /></code><br /><br />Delete 500K records from t5.<br /><br /><code><br />mysql> set ndb_use_transactions=0;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delete from t5 limit 100000;<br />Query OK, 100000 rows affected (2.73 sec)<br /><br />mysql> delete from t5 limit 100000;<br />Query OK, 100000 rows affected (3.13 sec)<br /><br />mysql> delete from t5 limit 100000;<br />Query OK, 100000 rows affected (3.11 sec)<br /><br />mysql> delete from t5 limit 100000;<br />Query OK, 100000 rows affected (3.13 sec)<br /><br />mysql> delete from t5 limit 100000;<br />Query OK, 100000 rows affected (2.97 sec)<br /></code><br /><br />Memory usage after deletion:<br /><br /><code><br />Node 2: Data usage is 45%(14890 32K pages of total 32768)<br />Node 2: Index usage is 19%(3120 8K pages of total 16416)<br />ndb_mgm> Node 3: Data usage is 45%(14890 32K pages of total 32768)<br />Node 3: Index usage is 19%(3121 8K pages of total 16416)<br /></code><br /><br />Run OPTIMIZE TABLE:<br /><br /><code><br />mysql> optimize table t5;<br />+---------+----------+----------+----------+<br />| Table   | Op       | Msg_type | Msg_text |<br />+---------+----------+----------+----------+<br />| test.t5 | optimize | status   | OK       |<br />+---------+----------+----------+----------+<br />1 row in set (1 min 41.94 sec)<br /><br /></code><br /><br />CPU UTIL during OPTIMIZE TABLE:<br />User:23.8%   Sys: 4.9%  ndbd               <br /><br />Memory usage after OPTIMIZE TABLE:<br /><br /><code>                  <br />ndb_mgm> Node 2: Data usage is 39%(13090 32K pages of total 32768)<br />Node 2: Index usage is 19%(3120 8K pages of total 16416)<br />Node 3: Data usage is 39%(13090 32K pages of total 32768)<br />Node 3: Index usage is 19%(3121 8K pages of total 16416)<br /></code>                                                                              <br />  <br />Delete 500K (50%) of the records from t6:<br /><code><br />mysql> set ndb_use_transactions=0;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />mysql> delete from t6 limit 100000;<br />Query OK, 100000 rows affected (2.77 sec)<br /><br />mysql> delete from t6 limit 100000;<br />Query OK, 100000 rows affected (3.05 sec)<br /><br />mysql> delete from t6 limit 100000;<br />Query OK, 100000 rows affected (3.12 sec)<br /><br />mysql> delete from t6 limit 100000;<br />Query OK, 100000 rows affected (3.19 sec)<br /><br />mysql> delete from t6 limit 100000;<br />Query OK, 100000 rows affected (3.24 sec)<br /></code><br /><br />Memory usage after deletion:<br /><br /><code><br />Node 2: Data usage is 39%(13090 32K pages of total 32768)<br />Node 2: Index usage is 15%(2521 8K pages of total 16416)<br />Node 3: Data usage is 39%(13090 32K pages of total 32768)<br />Node 3: Index usage is 15%(2522 8K pages of total 16416)<br /></code><br /><br />Run OPTIMIZE TABLE:<br /><br /><code><br />mysql> optimize table t6;<br />+---------+----------+----------+----------+<br />| Table   | Op       | Msg_type | Msg_text |<br />+---------+----------+----------+----------+<br />| test.t6 | optimize | status   | OK       |<br />+---------+----------+----------+----------+<br />1 row in set (1 min 45.83 sec)<br /></code><br /><br />Memory usage after OPTIMIZE TABLE:<br /><br /><code><br />Node 2: Data usage is 28%(9249 32K pages of total 32768)<br />Node 2: Index usage is 15%(2521 8K pages of total 16416)<br />Node 3: Data usage is 28%(9249 32K pages of total 32768)<br />Node 3: Index usage is 15%(2522 8K pages of total 16416)<br /></code><br /><br />After restart of node 3:<br /><br /><code><br />Node 2: Data usage is <span>28%</span>(9249 32K pages of total 32768)<br />Node 2: Index usage is 15%(2521 8K pages of total 16416)<br />Node 3: Data usage is <span>26%</span>(8568 32K pages of total 32768)<br />Node 3: Index usage is 13%(2236 8K pages of total 16416)<br /></code><br /><br />Only two percent diff between rolling restart and OPTIMIZE TABLE. Excellent. Thank you Jonas for fixing this.<div><img width="1" height="1" src="https://blogger.googleusercontent.com/tracker/19281624-5203467964097763594?l=johanandersson.blogspot.com" /></div>]]></content:encoded>
			<wfw:commentRss>http://planetmysql.ru/2009/08/04/optimize-table-on-cluster-revisited/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

