<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7187715604634812015</id><updated>2011-08-03T10:29:46.032-07:00</updated><category term='sandbox'/><category term='mysql replication'/><category term='mysql maatkit'/><category term='mysql'/><category term='mac'/><title type='text'>The Bungling DBA</title><subtitle type='html'>I'm a DBA.  Sometimes I make dumb mistakes and write about them so they don't get repeated.  Sometimes I do clever things and try to share them here.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>6</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-5884768497734082656</id><published>2010-10-12T15:02:00.000-07:00</published><updated>2010-10-12T15:15:38.434-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql maatkit'/><title type='text'>Maatkit Table Sync</title><content type='html'>I use different Maatkit tools almost every day, but until recently I hadn't needed to use mk-table-sync.  I will briefly document what I did here so that Future Me can refer back to it.&lt;br /&gt;&lt;br /&gt;What happened: A long running query on a slave had to be killed and skipped in order to get critical reporting back up to date.  We needed to diff the tables between master and slave and fill in the holes on the slave.  The table in question has an auto-increment PK, so it was an excellent candidate to use the Maatkit table sync script.&lt;br /&gt;&lt;br /&gt;Get the tool:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;wget http://www.maatkit.org/get/mk-table-sync&lt;br /&gt;chmod +x mk-table-sync&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I ran it from the slave db like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;./mk-table-sync --print --user=foo --ask-pass --tables=db.table_to_fix --nocheck-triggers --sync-to-master slave_db_name&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;I used --print to generate a list of sql statements to run.  I could have used --execute to simply have them run, but I wanted to look at the changes that would be made first.  --nocheck-triggers was used because the table had triggers on it.  I verified that inserting the missing rows would not affect what the triggers did, so I felt comfortable using that option.&lt;br /&gt;&lt;br /&gt;The script very intelligently examined the table on both master and slave in small chunks to determine missing rows.  There was no adverse affect in my case on either master or slave.  The end result was a list of about 1400 REPLACE statement that I verified and then used to fix the problem.&lt;br /&gt;&lt;br /&gt;Great tool!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-5884768497734082656?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/5884768497734082656/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2010/10/maatkit-table-sync.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/5884768497734082656'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/5884768497734082656'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2010/10/maatkit-table-sync.html' title='Maatkit Table Sync'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-1823681455250208660</id><published>2010-03-11T15:13:00.000-08:00</published><updated>2010-03-11T15:15:20.663-08:00</updated><title type='text'>Testing code formatting</title><content type='html'>&lt;pre class="brush: perl"&gt;&lt;br /&gt;&lt;br /&gt;use strict;&lt;br /&gt;use warnings;&lt;br /&gt;use Getopt::Long;&lt;br /&gt;&lt;br /&gt;my $sleep_interval = 10; # default is 10 seconds&lt;br /&gt;my $server_list;&lt;br /&gt;&lt;br /&gt;GetOptions (    'interval=i' =&gt; \$sleep_interval,&lt;br /&gt;                'server-list=s' =&gt; \$server_list&lt;br /&gt;            );&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-1823681455250208660?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/1823681455250208660/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2010/03/testing-code-formatting.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/1823681455250208660'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/1823681455250208660'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2010/03/testing-code-formatting.html' title='Testing code formatting'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-2890406736570655913</id><published>2009-08-07T12:08:00.000-07:00</published><updated>2009-08-07T12:44:39.473-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><title type='text'>Another reason to delete default MySQL users</title><content type='html'>One of the first things that I always do when I bring up a new MySQL instance is to delete the two users that are created with no user name or password.  I consider it an important step in securing the database.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;It turns out there is another very good reason to get rid of those accounts.  This is probably an edge case, but it took me a bit of time to figure it out so I'll post it here.  Some of our developers transferred all of the user grants from a dev mysql instance they had set up to a new box for testing.  Unfortunately they hadn't removed the user accounts with an empty string as the user name, so they were transferred as well.  This lead to a case where mysql logins from the dev box would fail when attempted on the new box.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;After the grants were set up, here is what they looked like on the new box:&lt;/div&gt;&lt;table border="1"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;th&gt;User:&lt;/th&gt;&lt;th&gt;Host:&lt;/th&gt;&lt;th&gt;Password:&lt;/th&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;foo&lt;/td&gt;&lt;td&gt;10.%&lt;/td&gt;&lt;td&gt;[password hash]&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;[empty string]&lt;/td&gt;&lt;td&gt;10.1.1.1&lt;/td&gt;&lt;td&gt;[empty string - no password]&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;[The second one is the default account that should have been removed]&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Login attempts using foo worked from all hosts except from 10.1.1.1.  What was happening was that MySQL was evaluating the incoming access request from 10.1.1.1 using the ''@10.1.1.1 credentials.  It clearly started with the most specific match on the host ip and then accepted the '' user name as a wildcard - so 'foo' was OK.  At that point the passwords would not match and an error is thrown to the user on 10.1.1.1.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;You can verify this by attempting to log in as foo from 10.1.1.1 with no password.  This lets you in with the grants for the ''@10.1.1.1 account.  Or removing the ''@10.1.1.1 user will allow the foo@10.% account to match correctly against the provided credentials.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Like I said, this is definitely an edge case - but it did provide a good learning experience for me to dig a little deeper into how MySQL evaluates incoming connections against the grant tables.  Sometimes things aren't how you would expect!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-2890406736570655913?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/2890406736570655913/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2009/08/another-reason-to-delete-default-mysql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/2890406736570655913'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/2890406736570655913'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2009/08/another-reason-to-delete-default-mysql.html' title='Another reason to delete default MySQL users'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-5880747516103977712</id><published>2009-07-27T17:59:00.000-07:00</published><updated>2009-07-27T18:16:33.675-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql replication'/><title type='text'>Modifying a 3 step replication chain</title><content type='html'>Some of our MySQL replication chains look like this:&lt;br /&gt;&lt;br /&gt;Server A --&gt; Server B --&gt; Server C&lt;br /&gt;Server A --&gt; Server D&lt;br /&gt;&lt;br /&gt;I needed to change the overall replication configuration so it looked like this:&lt;br /&gt;&lt;br /&gt;Server A --&gt; Server B&lt;br /&gt;Server A --&gt; Server D --&gt; Server C&lt;br /&gt;&lt;br /&gt;The trick was in getting B and D to stop at the same position.  It wasn't too hard, but I got to use an option with 'start slave' that I hadn't used before.&lt;br /&gt;&lt;br /&gt;The steps that I used were:&lt;br /&gt;&lt;br /&gt;1) Make sure replication is caught up on B, D, and C.&lt;br /&gt;&lt;br /&gt;2) Stop the slaves on B and D.&lt;br /&gt;&lt;br /&gt;3) Run 'flush logs' on A.  Then 'show master status' to see the new binary log number it advanced to.&lt;br /&gt;&lt;br /&gt;4) On B and D I ran: start slave until master_log_file = 'new file above', master_log_pos = 98;&lt;br /&gt;This advances B and D to the same log position (the beginning of the new binary log we started in the previous step) and then stops the sql_thread.&lt;br /&gt;&lt;br /&gt;5) Make sure C is caught up, then run 'stop slave'.&lt;br /&gt;&lt;br /&gt;6) Run 'reset master' on D.  I do this to clean up binary logs we don't need and get a fresh start position.&lt;br /&gt;&lt;br /&gt;7) Re-master C: change master to master_host = 'D', master_log_file = 'mysql-bin.000001', master_log_pos = 98, master_user = 'foo', master_password = 'bar';&lt;br /&gt;&lt;br /&gt;8) Restart all of the slaves and verify replication is working as expected.&lt;br /&gt;&lt;br /&gt;You don't need to do the step where you flush logs on A, but I prefer it because it gives me a known log file that hasn't been processed yet.  I like using the position '98' as well because I know it's the beginning of a binary log file.  Similarly you needn't 'reset master' in step 6 (you could use the existing log file positions), but I like to have a clean start.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-5880747516103977712?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/5880747516103977712/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/modifying-3-step-replication-chain.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/5880747516103977712'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/5880747516103977712'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/modifying-3-step-replication-chain.html' title='Modifying a 3 step replication chain'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-7733140093273094454</id><published>2009-07-15T14:09:00.000-07:00</published><updated>2009-07-15T14:18:52.717-07:00</updated><title type='text'>Binlog Sync in MySQL</title><content type='html'>I had an interesting case today where a master had a surprise reboot.  Upon recovery we saw that the slave db had processed a few records from the master that hadn't made it into the binlog on the master host.  This ran contrary to my mental model of MySQL replication where statements were not picked up by the slave until written to the binary log and then pulled. &lt;br /&gt;&lt;br /&gt;So I learned all about the &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/replication-options-binary-log.html#sysvar_sync_binlog"&gt;sync-binlog&lt;/a&gt; parameter.  Default behavior is to rely upon the native filesystem for writes to the binlog, so they may be in the filesystem cache before actually getting written.  If your system goes down in that state those statements will have been sent to the slave, but not actually written to the master binlog.&lt;br /&gt;&lt;br /&gt;Note that this issue also threw an error on the slave as it tried to start replicating from a binlog position that hadn't actually been written to the binlog file.&lt;br /&gt;&lt;br /&gt;Nice to learn something new :).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-7733140093273094454?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/7733140093273094454/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/binlog-sync-in-mysql.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/7733140093273094454'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/7733140093273094454'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/binlog-sync-in-mysql.html' title='Binlog Sync in MySQL'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7187715604634812015.post-308184975827168530</id><published>2009-07-02T13:31:00.000-07:00</published><updated>2009-07-02T13:40:56.344-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='sandbox'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='mac'/><title type='text'>Setting up MySQL Sandbox and MySQL 5.4 on OS X</title><content type='html'>After the announcement of MySQL 5.4 I wanted to set up a test environment on my Macbook Pro to check it out.  It turned out to be pretty easy, but I will document the steps here for future reference:&lt;br /&gt;&lt;br /&gt;Download the source code from mysql: &lt;a href="http://dev.mysql.com/downloads/mysql/5.4.html#source"&gt;http://dev.mysql.com/downloads/mysql/5.4.html#source&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;I did the following steps as the superuser.&lt;br /&gt;&lt;br /&gt;After expanding the tarball I compiled it like so:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;./configure --prefix=/Users/dcr/opt/mysql/5.4.0 --enable-dtrace --enable-profiling --with-plugins=all&lt;br /&gt;&lt;br /&gt;make&lt;br /&gt;make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;The next step is to download the latest MySQL Sandbox: &lt;a href="https://launchpad.net/mysql-sandbox/+download"&gt;https://launchpad.net/mysql-sandbox/+download&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This also has a super easy install:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;tar zxvf MySQL-Sandbox-3.0.04.tar.gz&lt;br /&gt;cd MySQL-Sandbox-3.0.04&lt;br /&gt;perl Makefile&lt;br /&gt;make&lt;br /&gt;make test&lt;br /&gt;make install&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;Once that's done the mysql-sandbox scripts will be installed in /usr/bin.&lt;br /&gt;&lt;br /&gt;Setting up the 5.4 sandbox is now a matter of a single command:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;make_sandbox 5.4.0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;This works because mysql sandbox looks for the mysql system files in ~/opt/mysql/n.n.n, where n.n.n is the version number (5.4.0 in our case).&lt;br /&gt;&lt;br /&gt;The sandbox is created in ~/sandboxes/msb_5_4_0.  From that directory you can manage it in the usual ways.&lt;br /&gt;&lt;br /&gt;Additionally, adding other versions of mysql for use in the sandbox is easy.  Just download the os x tar.gz file from mysql, expand it, and move the contents to ~/opt/mysql/n.n.n (substituting the actual version number in the path).&lt;br /&gt;&lt;br /&gt;Using these steps I had a fully functional test instance up and running in just a few minutes (most of which was compile time for 5.4).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7187715604634812015-308184975827168530?l=bunglingdba.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://bunglingdba.blogspot.com/feeds/308184975827168530/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/setting-up-mysql-sandbox-and-mysql-54.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/308184975827168530'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7187715604634812015/posts/default/308184975827168530'/><link rel='alternate' type='text/html' href='http://bunglingdba.blogspot.com/2009/07/setting-up-mysql-sandbox-and-mysql-54.html' title='Setting up MySQL Sandbox and MySQL 5.4 on OS X'/><author><name>dcr</name><uri>http://www.blogger.com/profile/04726108835318801611</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
