<?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-6864099895737809960</id><updated>2011-08-17T05:10:10.440+02:00</updated><category term='mysql ndb-api memory leak'/><category term='mysql'/><category term='MySQL cluster convert innodb myisam error index file'/><category term='blog'/><category term='move'/><category term='mysql maintenance jobs'/><title type='text'>Shinguz' Blog</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>26</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-7812095097270660100</id><published>2010-04-01T10:17:00.003+02:00</published><updated>2010-04-01T10:21:55.890+02:00</updated><title type='text'>Shinguz's Blog moves to company website</title><content type='html'>Hello dear readers,&lt;br /&gt;&lt;br /&gt;I will move my blog to our company website: http://www.fromdual.com/blog&lt;br /&gt;&lt;br /&gt;My personal blog you can find as follows: http://www.fromdual.ch/blog/41/feed&lt;br /&gt;&lt;br /&gt;Thanks to you all and see us there!&lt;br /&gt;&lt;br /&gt;Regards,&lt;br /&gt;Oli (aka Shinguz)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-7812095097270660100?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7812095097270660100'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7812095097270660100'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/04/shinguzs-blog-moves-to-company-website.html' title='Shinguz&apos;s Blog moves to company website'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-4859681384674253461</id><published>2010-03-01T12:11:00.004+01:00</published><updated>2010-03-01T13:54:29.822+01:00</updated><title type='text'>FromDual - The MySQL consulting company goes operational today!</title><content type='html'>Hello everybody,&lt;br /&gt;&lt;br /&gt;One month earlier than planned we have the great pleasure to announce you that the company called &lt;a href="http://www.fromdual.com/" target="blank"&gt;FromDual&lt;/a&gt; goes operational today!&lt;br /&gt;&lt;br /&gt;We are excited about this step and it is an new era in our personal evolution to get back in full-contact with customers and solve their real life day-to-day MySQL problems.&lt;br /&gt;&lt;br /&gt;So we are happy hearing from you and to help you solving your individual MySQL problems...&lt;br /&gt;&lt;br /&gt;You can find us at &lt;a href="http://www.fromdual.com/" target="_blank"&gt;FromDual&lt;/a&gt; or you can &lt;a href="mailto:oli.sennhauser@fromdual.com"&gt;drop us a line&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Regards,&lt;br /&gt;Oli Sennhauser (aka Shinguz)&lt;br /&gt;Senior MySQL Consultant at FromDual&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;About FromDual&lt;/h3&gt;FromDual provides neutral and vendor independent MySQL consulting, training and other services around MySQL and its derivatives. The company concentrates on the individual needs of its customers and achieves, in a close co-operation the best results for their problems.&lt;br /&gt;&lt;br /&gt;Our consultants have been working in many projects in Europe. We were involved in small start-ups, medium size enterprises and huge world wide operating top-500 companies and solved their Performance Problems, developed Architecture &amp;amp; Design studies with them, answered their operation questions, and reviewed their Backup/Recovery concepts.&lt;br /&gt;&lt;br /&gt;FromDual does on-site and remote consulting, remote emergency aid and helps its customers to fill MySQL staff gaps if needed.&lt;br /&gt;&lt;br /&gt;The company is privately owned. Its HQ is close to Zurich in Switzerland.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-4859681384674253461?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/4859681384674253461/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=4859681384674253461' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/4859681384674253461'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/4859681384674253461'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/03/fromdual-mysql-consulting-company-goes.html' title='FromDual - The MySQL consulting company goes operational today!'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-730912821212264602</id><published>2010-02-15T16:18:00.006+01:00</published><updated>2010-02-15T16:39:06.387+01:00</updated><title type='text'>Logging users to the MySQL error log</title><content type='html'>&lt;h2&gt;Problem&lt;/h2&gt;A customer recently showed up with the following problem:&lt;br /&gt;&lt;blockquote style="font-style: italic;"&gt;With your guidelines [1] I am now able to send the MySQL error log to the syslog&lt;br /&gt;and in particular to an external log server.&lt;br /&gt;But I cannot see which user connects to the database in the error log.&lt;br /&gt;&lt;br /&gt;How can I achieve this?&lt;br /&gt;&lt;/blockquote&gt;&lt;h2 style=""&gt;Idea&lt;/h2&gt;During night when I slept my brain worked independently on this problem and in the morning he had prepared a possible solution for it.&lt;br /&gt;&lt;br /&gt;What came out is the following:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;We create an UDF which allows an application to write to the MySQL error log.&lt;br /&gt;See my previous article about this [2].&lt;br /&gt;&lt;/li&gt;&lt;li&gt;We specify in a simple SQL query how the string should look which we want to write to the MySQL error log file.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;We use the &lt;span style="font-family:courier new;"&gt;init_connect&lt;/span&gt; [3] hook (= logon trigger) which MySQL provides to log the information to the error log.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h2&gt;How to solve it?&lt;/h2&gt;The UDF can be taken from [4]. Be not confused by the version number. It just worked with MySQL 5.1.42. Load the UDF according to the article into the MySQL database. Follow the little example there and if it works lets continue to the next step.&lt;br /&gt;&lt;br /&gt;The SQL query to form the MySQL error log string looks as follows:&lt;br /&gt;&lt;pre&gt;  mysql&gt; SELECT CONCAT('[Security] User ', USER(), ' logged in.');&lt;/pre&gt;And if executed with the function:&lt;br /&gt;&lt;pre&gt;  mysql&gt; SELECT log_error(CONCAT('[Security] User ', USER(), ' logged in.'));&lt;/pre&gt;it produces the following output to the MySQL error log file:&lt;br /&gt;&lt;pre&gt;  shell&gt; tail -n 1 error.log&lt;br /&gt;       100215 17:50:16 [Security] User oli@localhost logged in.&lt;/pre&gt;And now make this permanent for every user which does not have SUPER privileges:&lt;br /&gt;&lt;pre&gt;  #&lt;br /&gt;  # my.cnf&lt;br /&gt;  #&lt;br /&gt;  [mysqld]&lt;br /&gt;  init_connect = 'SELECT log_error(CONCAT("[Security] User ", USER(), " logged in."));'&lt;/pre&gt;restart the database and it should work now (it could also work with just &lt;span style="font-family:courier new;"&gt;SET GLOBAL init_connect=...&lt;/span&gt;).&lt;br /&gt;&lt;h2&gt;Caution&lt;/h2&gt;Please consider the MySQL documentation [3] and be aware of the following:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;"Note that the content of init_connect is not executed for users that have the SUPER privilege."&lt;/span&gt;&lt;/blockquote&gt;Further I want to warn you that I have NOT tested the impact on stability and performance of this method! Please test it carefully yourself an let me know if you find something or also if it works smoothly for you.&lt;br /&gt;&lt;br /&gt;This is part of the MySQL Auditing Package we are currently working on and we hope to finish it soon. If you are interested in this work please let us know and our &lt;a href="http://www.fromdual.com/our-services" target="_blank"&gt;MySQL consultants&lt;/a&gt; are happy to help you implementing your own MySQL auditing in your environment.&lt;br /&gt;&lt;h2&gt;Literature&lt;/h2&gt;[1] &lt;a href="http://shinguz.blogspot.com/2010/01/mysql-reporting-to-syslog.html" 2009="" 10="" com="" doc="" refman="" 1="" en="" sysvar_init_connect="" ch="" mysql="" html="" target=""&gt;MySQL reporting to syslog&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://shinguz.blogspot.com/2009/10/mysql-useful-add-on-collection-using.html"&gt;MySQL useful add-on collection using UDF&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/server-system-variables.html#sysvar_init_connect" target="_blank"&gt;MySQL documentation: init_connect&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://www.shinguz.ch/MySQL/mysql-useful-udf-collection.html" target="_blank"&gt;UDF collection&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-730912821212264602?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/730912821212264602/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=730912821212264602' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/730912821212264602'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/730912821212264602'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/02/logging-users-to-mysql-error-log.html' title='Logging users to the MySQL error log'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-7310956598095706640</id><published>2010-02-11T22:06:00.002+01:00</published><updated>2010-02-11T22:24:19.990+01:00</updated><title type='text'>Can you trust your backup?</title><content type='html'>Today a customer with corrupted data files showed up. When we enquired a bit more he told us that he had a broken I/O controller. This is one of the worst things which can happen to you!&lt;br /&gt;&lt;br /&gt;The reason is the following: When a I/O controller starts to die it often does not happen immediately. The controller dies slowly producing more and more corrupt data. When you just write data without checking or reading them it can take days or even weeks until you discover the problem.&lt;br /&gt;&lt;br /&gt;But the nasty thing is, that even your backup is infected with the corrupted data. In worst case corruption started long before your oldest still existing backup was made.&lt;br /&gt;&lt;br /&gt;Fortunately DBMS are a bit sensitive related to data corruptions and start to complain pretty early. So please consider warning or error messages about data corruption as serious and try to find the problem immediately and solve it!&lt;br /&gt;&lt;br /&gt;What can we do against spreading data corruption?&lt;ul&gt;&lt;br /&gt;&lt;li&gt;Monitor logs (syslog, database error log, application log, etc.).&lt;/li&gt;&lt;li&gt;Ideally do physical AND logical backups. If your database is too big for a logical restore you can redirect your logical backup to &lt;code&gt;/dev/null&lt;/code&gt;. So you can assure that at least the data can be read and the mysqldump command should complain when you hit data corruption (does not work for index corruption!).&lt;/li&gt;&lt;li&gt;Think about a backup retention policy.&lt;/li&gt;&lt;li&gt;Think about 2 independent paths to recover your data (keep at least 2 good backups + all the binary logs).&lt;/li&gt;&lt;li&gt;Do a check on your backuped files (myisamchk, innochecksum).&lt;/li&gt;&lt;li&gt;Test your backup frequently with a restore (ideally on a daily basis)!&lt;/li&gt;&lt;/ul&gt;Unfortunately this last item is done much to rare by MySQL users and then they experience bad surprises when they have to do a restore once in an emergency!&lt;br /&gt;&lt;br /&gt;Have you EVER tested a restore of your backup? Please do! Especially if your data size is significant bigger than your amount of RAM!&lt;br /&gt;&lt;br /&gt;In a later article I will show you a concept to do backups and test the restores regularly. Including some positive side effects on your development process.&lt;br /&gt;&lt;br /&gt;If you need some more information or help about backup concepts, emergency restore or data recoveries please consider our &lt;a href="http://www.fromdual.com/our-services" target="_blank"&gt;consulting services&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-7310956598095706640?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/7310956598095706640/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=7310956598095706640' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7310956598095706640'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7310956598095706640'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/02/can-you-trust-your-backup.html' title='Can you trust your backup?'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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-6864099895737809960.post-3436369063170590707</id><published>2010-01-29T21:37:00.004+01:00</published><updated>2010-01-29T22:07:25.265+01:00</updated><title type='text'>What is CHECK TABLE doing with InnoDB tables?</title><content type='html'>Recently we had a case where a customer got some corrupted blocks in his InnoDB tables. His largest tables where quite big, about 30 to 100 Gbyte. Why he got this corrupted blocks we did not find out yet (disk broken?).&lt;br /&gt;&lt;br /&gt;When you have corrupted blocks in InnoDB, it is mandatory to get rid of them again. Otherwise your database can crash suddenly.&lt;br /&gt;If you are lucky only "normal" tables are concerned. So you can dump, drop, recreate and load them again as described in the InnoDB recovery procedure in the MySQL documentation [1].&lt;br /&gt;If you are not so lucky you have to recreate your complete database or go back to an old backup and do a restore with a Point-in-Time-Recovery (PITR).&lt;br /&gt;&lt;br /&gt;To find out if some tables are corrupted MySQL provides 2 tools: The innochecksum utility [2] and the mysqlcheck utility [3] or you can use the CHECK TABLE command manually (which is used by mysqlcheck).&lt;br /&gt;&lt;br /&gt;I wanted to know how CHECK TABLE works in detail. So I looked first in the MySQL documentation [4]. But unfortunately the MySQL documentation does not go into details that much very often on such specific questions.&lt;br /&gt;&lt;br /&gt;So I dug into the code. The interesting lines you can find in the files handler/ha_innodb.cc and row/row0mysql.c. In the following snippets I have cut out a lot of detail stuff.&lt;br /&gt;&lt;br /&gt;The function ha_innobase::check is the interface between the CHECK TABLE command and the InnoDB storage engine and does the call of the InnoDB table check:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;// handler/ha_innodb.cc&lt;br /&gt;&lt;br /&gt;int ha_innobase::check( THD* thd )&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);&lt;br /&gt;&lt;br /&gt;  ret = row_check_table_for_mysql(prebuilt);&lt;br /&gt;&lt;br /&gt;  if (ret == DB_SUCCESS) {&lt;br /&gt;    return(HA_ADMIN_OK);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return(HA_ADMIN_CORRUPT);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;The function row_check_table_for_mysql does the different checks on an InnoDB table:&lt;ul&gt;&lt;br /&gt;  &lt;li&gt;First it checks if the ibd file is missing.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Then the first index (dict_table_get_first_index) is checked on its consistency (btr_validate_index) by walking through all page tree levels. In InnoDB the first (primary) index is always equal to the table (= data).&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;If the index is consistent several other checks are performed (row_scan_and_check_index):&lt;br /&gt;    &lt;ul&gt;&lt;br /&gt;      &lt;li&gt;If entries are in ascendant order.&lt;/li&gt;&lt;br /&gt;      &lt;li&gt;If unique constraint is not broken.&lt;/li&gt;&lt;br /&gt;      &lt;li&gt;And the number of index entries is calculated.&lt;/li&gt;&lt;/ul&gt;&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Then the next and all other (secondary) indexes of the table are done in the same way.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;At the end a WHOLE Adaptive Hash Index check for ALL InnoDB tables (btr_search_validate) is done for every CHECK TABLE!&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;pre&gt;// row/row0mysql.c&lt;br /&gt;&lt;br /&gt;ulint row_check_table_for_mysql( row_prebuilt_t* prebuilt )&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  if ( prebuilt-&gt;table-&gt;ibd_file_missing ) {&lt;br /&gt;    fprintf(stderr, "InnoDB: Error: ...", prebuilt-&gt;table-&gt;name);&lt;br /&gt;    return(DB_ERROR);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  index = dict_table_get_first_index(table);&lt;br /&gt;&lt;br /&gt;  while ( index != NULL ) {&lt;br /&gt;&lt;br /&gt;    if ( ! btr_validate_index(index, prebuilt-&gt;trx) ) {&lt;br /&gt;      ret = DB_ERROR;&lt;br /&gt;    }&lt;br /&gt;    else {&lt;br /&gt;&lt;br /&gt;      if ( ! row_scan_and_check_index(prebuilt, index, &amp;n_rows) ) {&lt;br /&gt;        ret = DB_ERROR;&lt;br /&gt;      }&lt;br /&gt;&lt;br /&gt;      if ( index == dict_table_get_first_index(table) ) {&lt;br /&gt;        n_rows_in_table = n_rows;&lt;br /&gt;      }&lt;br /&gt;      else if ( n_rows != n_rows_in_table ) {&lt;br /&gt;&lt;br /&gt;        ret = DB_ERROR;&lt;br /&gt;&lt;br /&gt;        fputs("Error: ", stderr);&lt;br /&gt;        dict_index_name_print(stderr, prebuilt-&gt;trx, index);&lt;br /&gt;        fprintf(stderr, " contains %lu entries, should be %lu\n", n_rows, n_rows_in_table);&lt;br /&gt;      }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;    index = dict_table_get_next_index(index);&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  if ( ! btr_search_validate() ) {&lt;br /&gt;    ret = DB_ERROR;&lt;br /&gt;  }&lt;br /&gt;&lt;br /&gt;  return(ret);&lt;br /&gt;}&lt;/pre&gt;&lt;br /&gt;A little detail which is NOT discussed in the code above is that the fatal lock wait timeout is set from 600 seconds (10 min) to 7800 seconds (2 h 10 min).&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;/* Enlarge the fatal lock wait timeout during CHECK TABLE. */&lt;br /&gt;mutex_enter(&amp;kernel_mutex);&lt;br /&gt;srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */&lt;br /&gt;mutex_exit(&amp;kernel_mutex);&lt;/pre&gt;&lt;br /&gt;As far as I understand this has 2 impacts:&lt;ol&gt;&lt;li&gt;CHECK TABLE for VERY large tables (&gt; 200 - 400 Gbyte) will most probably fail because it will  exceed the fatal lock timeout. This becomes more probable when you have bigger tables, slower disks, less memory or do not make use of your memory appropriately.&lt;/li&gt;&lt;br /&gt;  &lt;li&gt;Because srv_fatal_semaphore_wait_threshold is a global variable, during every CHECK TABLE the fatal lock wait timeout is set high for the whole system. Long enduring InnoDB locks will be detected late or not at all during a long running CHECK TABLE command.&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;If this is something which should be fixed to get a higher reliability of the system I cannot judge and is up to the InnoDB developers. But when you hit such symptoms during long running CHECK TABLE commands consider this.&lt;br /&gt;For the first finding I have filed a feature request [5]. This "problem" was introduced long time ago with bug #2694 [6] in MySQL 4.0, Sep 2004. Thanks to Axel and Shane for their comments.&lt;br /&gt;If you want to circumvent this situation you have either to recompile MySQL with higher values or you can use the concept of a pluggable User Defined Function (UDF) which I have described earlier [7], [8], [9].&lt;br /&gt;&lt;br /&gt;An other detail is that at the end of each CHECK TABLE command a check of all Adaptive Hash Indexes of all tables is done. I do not know how expensive it is to check all Adaptive Hash Indexes, especially when they are large. But having a more optimized code there could help to speed up the CHECK TABLE command for a small percentage?&lt;br /&gt;&lt;br /&gt;These information are valid up to MySQL/InnoDB 5.1.41 and the InnoDB plug-in 1.0.5.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Literature&lt;/h2&gt;[1] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/forcing-recovery.html" target="_blank"&gt;Forcing InnoDB Recovery&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/innochecksum.html" target="_blank"&gt;innochecksum — Offline InnoDB File Checksum Utility&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysqlcheck.html" target="_blank"&gt;mysqlcheck&lt;/a&gt;&lt;br /&gt;[4] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/check-table.html" target="_blank"&gt;CHECK TABLE&lt;/a&gt;&lt;br /&gt;[5] &lt;a href="http://bugs.mysql.com/bug.php?id=50723" target="_blank"&gt;Bug #50723: InnoDB CHECK TABLE fatal semaphore wait timeout possibly too short for big table&lt;/a&gt;&lt;br /&gt;[6] &lt;a href="http://bugs.mysql.com/bug.php?id=2694" target="_blank"&gt;Bug #2694: CHECK TABLE for Innodb table can crash server&lt;/a&gt;&lt;br /&gt;[7] &lt;a href="http://www.shinguz.ch/MySQL/mysql-useful-udf-collection.html" target="_blank"&gt;MySQL useful add-on collection using UDF&lt;/a&gt;&lt;br /&gt;[8] &lt;a hef="http://shinguz.blogspot.com/2009/10/using-mysql-user-defined-functions-udf.html" target="_blank"&gt;Using MySQL User-Defined Functions (UDF) to get MySQL internal informations&lt;/a&gt;&lt;br /&gt;[9] &lt;a href="http://shinguz.blogspot.com/2009/10/mysql-useful-add-on-collection-using.html" target="_blank"&gt;MySQL useful add-on collection using UDF&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.fosdem.org"&gt;&lt;img src="http://www.fosdem.org/promo/going-to" alt="I'm going to FOSDEM, the Free and Open Source Software Developers' European Meeting" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-3436369063170590707?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/3436369063170590707/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=3436369063170590707' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3436369063170590707'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3436369063170590707'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/01/what-is-check-table-doing-with-innodb.html' title='What is CHECK TABLE doing with InnoDB tables?'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-6451854101524594343</id><published>2010-01-22T17:05:00.002+01:00</published><updated>2010-01-22T17:10:15.528+01:00</updated><title type='text'>MySQL on VMware Workstation/DRBD vs. VMWare ESX Server/SAN</title><content type='html'>Or an active-active fail-over cluster à la VMware.&lt;br /&gt;&lt;br /&gt;Today I have learned about a totally crazy/cool looking architecture where the expensive VMware ESX server was replace by a free/cheap VMware Workstation version in combination with DRBD.&lt;br /&gt;&lt;br /&gt;Basically DRBD we name "the little man's SAN" and that is exactly what this customer is doing. He replaced the SAN with DRBD and now he can easily move one VMware instance to the other host. Possibly it is not that flexible and powerful as an ESX Server but also not so expensive...&lt;br /&gt;&lt;br /&gt;The architecture looks as follows:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_p9iYKIS3iFI/S1nNQ3LNGII/AAAAAAAAAAw/CViGDIS1YhA/s1600-h/vmware_drbd.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 320px; height: 235px;" src="http://4.bp.blogspot.com/_p9iYKIS3iFI/S1nNQ3LNGII/AAAAAAAAAAw/CViGDIS1YhA/s320/vmware_drbd.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5429596515344390274" /&gt;&lt;/a&gt;&lt;br /&gt;According to this customer it works stable on about a dozed of installations and they have not experienced any troubles during the fail-overs.&lt;br /&gt;&lt;br /&gt;Please let me know your experience, thoughts or concerns with this architecture...&lt;br /&gt;&lt;br /&gt;PS: When you consider such an architecture do not expect a very good performance!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-6451854101524594343?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/6451854101524594343/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=6451854101524594343' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6451854101524594343'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6451854101524594343'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/01/mysql-on-vmware-workstationdrbd-vs.html' title='MySQL on VMware Workstation/DRBD vs. VMWare ESX Server/SAN'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_p9iYKIS3iFI/S1nNQ3LNGII/AAAAAAAAAAw/CViGDIS1YhA/s72-c/vmware_drbd.png' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-7408954319385404737</id><published>2010-01-20T09:36:00.003+01:00</published><updated>2010-01-20T09:54:10.361+01:00</updated><title type='text'>The battle against Oracle is probably over but has the real war begun yet?</title><content type='html'>According to different sources from the web the decision about the Oracle - Sun merger has been approved by the European commission soon. So at least in the West it is clear what is going on. Let us see what the East decides... [1], [2].&lt;br /&gt;&lt;br /&gt;Oracles arch-enemy Microsoft has already brought its weapons in position against the target with its: "Microsoft offers Oracle-phobes MySQL migration tool" [3], [4]. So far so good. Nothing new, nothing special.&lt;br /&gt;&lt;br /&gt;What made me a bit edgy was the following Oracle blog series about their Oracle Warehouse Builder (OWB):&lt;br /&gt;&lt;ul&gt;&lt;li&gt;OWB 11gR2 – MySQL Open Connectivity  [5]&lt;/li&gt;&lt;li&gt;OWB 11gR2 – MySQL Bulk Extract [6]&lt;/li&gt;&lt;/ul&gt;OWB seems to be a great tool to move data around from different sources, to mix them and to extract some useful results.&lt;br /&gt;&lt;br /&gt;It looks like with the new 11gR2 release there "&lt;span style="font-style: italic;"&gt;... were significant changes to mapping to support native heterogeneous connectivity to systems ...&lt;/span&gt;".&lt;br /&gt;&lt;br /&gt;What interests me more is what is MySQL related about it. In the second part of the series I find some text passages like:&lt;br /&gt;&lt;br /&gt;"&lt;span style="font-style: italic;"&gt;Next on the MySQL series, let's look at bulk extract to file from MySQL. ... and also rather than just unloading to file, we can optimize for other systems such as Oracle and create Load Code Templates that extract in bulk from MySQL (or whatever) transfer to the Oracle system and create an external table as the staging table. ... Hopefully this gives you a taster for the capabilities of the bulk extract capabilities using MySQL as an illustration.&lt;/span&gt;"&lt;br /&gt;&lt;br /&gt;This makes me just a bit nervous. But hopefully I am just overreacting because of the current situation... So let us carefully watch how it continues!&lt;br /&gt;&lt;br /&gt;PS: .oO(How would it sound like this: "... and also rather than just unloading Oracle data to file, we can optimize for MySQL and create Load Code Templates that extract in bulk from Oracle (or whatever) transfer to the MySQL system ..."?)&lt;br /&gt;&lt;br /&gt;1 &lt;a href="http://news.yahoo.com/s/pcworld/20100118/tc_pcworld/oraclesunmergerfoesheadeast" target="_blank"&gt;Yahoo! NEWS&lt;/a&gt;&lt;br /&gt;2 &lt;a href="http://online.wsj.com/article/SB10001424052748704561004575013340483500722.html?mod=googlenews_wsj" target="_blank"&gt;The Wall Street Journal&lt;/a&gt;&lt;br /&gt;3 &lt;a href="http://www.the register.co.uk/2010/01/12/mysql_migration_sql_server/" target="_blank"&gt;Microsoft offers Oracle-phobes MySQL migration tool&lt;/a&gt;&lt;br /&gt;4 &lt;a href="http://blogs.technet.com/dataplatforminsider/archive/2010/01/11/free-download-microsoft-sql-server-migration-assistant.aspx" target="_blank"&gt;Free Download: Microsoft SQL Server Migration Assistant&lt;/a&gt;&lt;br /&gt;5 &lt;a href="http://blogs.oracle.com/warehousebuilder/2010/01/owb_11gr2_mysql_open_connectivity.html" target="_blank"&gt;OWB 11gR2 – MySQL Open Connectivity&lt;/a&gt;&lt;br /&gt;6 &lt;a href="http://blogs.oracle.com/warehousebuilder/2010/01/owb_11gr2_mysql_bulk_extract.html" target="_blank"&gt;OWB 11gR2 – MySQL Bulk Extract&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-7408954319385404737?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/7408954319385404737/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=7408954319385404737' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7408954319385404737'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/7408954319385404737'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/01/battle-against-oracle-is-probably-over.html' title='The battle against Oracle is probably over but has the real war begun yet?'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-5950634626513999862</id><published>2010-01-07T10:20:00.003+01:00</published><updated>2010-01-07T10:36:34.227+01:00</updated><title type='text'>MySQL reporting to syslog</title><content type='html'>There are 2 different possible situations you can face when you have to deal with MySQL and syslog:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;MySQL is used as back-end for syslog to store the logging information. [6]&lt;/li&gt;&lt;li&gt;MySQL itself should report to the syslog.&lt;/li&gt;&lt;/ol&gt;In this blog article we look at the second situation: How can you make MySQL reporting to the syslog.&lt;br /&gt;&lt;br /&gt;Since the version 5.1.20 MySQL is capable to log to the syslog [1], [2]. This is done by the MySQL angel process mysqld_safe.&lt;br /&gt;&lt;br /&gt;You can enable the syslog when you add the syslog parameter to the MySQL configuration file (my.cnf) in the mysqld_safe section:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;[mysqld_safe]&lt;br /&gt;syslog&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Currently MySQL is not capable to log to more than one logging facility at the same time. So you have to decide if you want to log either to the error log or to the syslog.&lt;br /&gt;&lt;br /&gt;If you specify both, syslog and error-log, at the same time you will receive an error message if you start mysqld like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;bin/mysqld_safe --defaults-file=/etc/my.cnf&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;But I assume that most of the MySQL users are using some kind of start/stop wrapper script like the mysql.server as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;/etc/init.d/mysql start&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;or&lt;br /&gt;&lt;br /&gt;&lt;code&gt;rcmysql start&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So you will never see the error message indicating you having a conflict between the syslog and the error log. And you are possibly wondering why it is not logging to the syslog. For this problem I have filed a bug report [3].&lt;br /&gt;&lt;br /&gt;If you cannot wait for the fix, this excerpt of mysqld_safe should help [8]:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;364   if [ $want_syslog -eq 1 ]&lt;br /&gt;365   then&lt;br /&gt;366     # User explicitly asked for syslog, so warn that it isn't used&lt;br /&gt;367     logging=file   # This line you have to add!&lt;br /&gt;368     log_error "Can't log to error log and syslog at the same time.  Remove all --log-error configuration options for --syslog to take effect."&lt;br /&gt;369   fi&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Logging to an other logging facility than daemon&lt;/h3&gt;&lt;br /&gt;Mysqld_safe uses the logger command to log the error messages to the syslog. With ps you will find a command which looks like this:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;logger -t mysqld -p daemon.error&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;The logger command uses 2 parameters -t for tag and -p for priority. The tag can be influenced with the syslog-tag parameter [4].&lt;br /&gt;The priority parameter configures into which facility and on which level the message should be logged.&lt;br /&gt;&lt;br /&gt;An exceprt from the logger man page [7]:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;Enter the message with the specified priority.  The priority may be specified numerically or as a ''facility.level'' pair.  For example, ''-p local3.info'' logs the message(s) as informational level in the local3 facility.  The default is ''user.notice.''&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Unfortunately the logging facility is hard-coded in the the mysqld_safe script as daemon.error and daemon.notice. It would be nice to have this parameter configurable as well thus I have filed a feature request for it [5].&lt;br /&gt;&lt;br /&gt;When you cannot wait, this code snippets from mysqld_safe possibly will help you [8]:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;26a27&lt;br /&gt;&gt; syslog_facility=daemon&lt;br /&gt;110c111&lt;br /&gt;&lt;&gt;&amp;amp;2&lt;br /&gt;---&lt;br /&gt;&gt;   log_generic $syslog_facility.error "$@" &gt;&amp;amp;2&lt;br /&gt;114c115&lt;br /&gt;&lt;&gt;   log_generic $syslog_facility.notice "$@"&lt;br /&gt;128c129&lt;br /&gt;&lt; cmd=""&gt;&amp;amp;1 | logger -t '$syslog_tag_mysqld' -p daemon.error"&lt;br /&gt;---&lt;br /&gt;&gt;       cmd="$cmd 2&gt;&amp;amp;1 | logger -t '$syslog_tag_mysqld' -p '$syslog_facility'.error"&lt;br /&gt;189a191&lt;br /&gt;&gt;       --syslog-facility=*) syslog_facility="$val" ;;&lt;br /&gt;366a369&lt;br /&gt;&gt;     logging=file&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;With the modified mysqld_safe you can change your MySQL configuration file (my.cnf) file as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;[mysqld_safe]&lt;br /&gt;syslog&lt;br /&gt;syslog-facility                 = local3&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;to log to the local3 logging facility for example.&lt;br /&gt;&lt;br /&gt;To activate this facility you possibly have to adapt your syslog configuration file (in my case: /etc/rsyslog.d/50-default.conf, in other cases: /etc/syslog.conf) as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;local3.*                        /var/log/database&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;To make these changes active you have to restart the syslog daemon:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;kill -KILL $(cat /var/run/rsyslogd.pid)&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;In my case kill -HUP was not strong enough because it did NOT display configuration errors in the log file.&lt;br /&gt;&lt;br /&gt;After the restart of the syslog daemon you should find the created empty log file and you can test if the logging works with the following command:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;logger -p local3.info test&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Now MySQL should log everything to your syslog facility local3.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;How to make MySQL logging to the error log AND the syslog facility?&lt;/h3&gt;&lt;br /&gt;Under normal circumstances mysqld_safe can not log to more than one logging facility.&lt;br /&gt;&lt;br /&gt;With the following syslog configuration you can make MySQL logging to both facilities, the error log AND the syslog. Add the following lines to your syslog configuration file:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;$FileOwner mysql&lt;br /&gt;$FileGroup dba&lt;br /&gt;local3.*                        /home/mysql/product/mysql-5.1.42/data/error.log&lt;br /&gt;&lt;br /&gt;# Set the owner and group back to its original values&lt;br /&gt;$FileOwner syslog&lt;br /&gt;$FileGroup adm&lt;br /&gt;local3.*                        /var/log/database&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;Then restart the syslog daemon as described above and you will see logging to both location. The only drawback is, that the messages in the MySQL error log look like the typical syslog messages and not like the typical MySQL error log messages any more. But this should be somehow configurable with the syslog parameters in its configuration file [9].&lt;br /&gt;&lt;br /&gt;If you need more assistance with logging to the syslog please feel free and &lt;a href="mailto:oli.sennhauser@bluewin.ch"&gt;drop me a line&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Literature&lt;/h3&gt;&lt;br /&gt;[1] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/error-log.html"&gt;MySQL error log &lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysqld-safe.html#option_mysqld_safe_syslog"&gt;mysqld_safe syslog parameter&lt;/a&gt;&lt;br /&gt;[3] &lt;a href="http://bugs.mysql.com/bug.php?id=50083"&gt;Bug #50083&lt;/a&gt;: error-log and syslog conflict in mysqld_safe is not reported to the log file.&lt;br /&gt;[4] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysqld-safe.html#option_mysqld_safe_syslog-tag"&gt;mysqld_safe syslog-tag parameter&lt;/a&gt;&lt;br /&gt;[5] &lt;a href="http://bugs.mysql.com/bug.php?id=50080"&gt;Bug #50080&lt;/a&gt;: syslog priority cannot be configured&lt;br /&gt;[6] &lt;a href="http://www.rsyslog.com/doc-rsyslog_mysql.html"&gt;Writing syslog messages to MySQL&lt;/a&gt;&lt;br /&gt;[7] &lt;a href="http://linux.die.net/man/1/logger"&gt;Logger man page&lt;/a&gt;&lt;br /&gt;[8] &lt;a href="http://www.shinguz.ch/MySQL/mysqld_safe_syslog"&gt;Modified mysqld_safe for advance syslog logging&lt;/a&gt;&lt;br /&gt;[9] &lt;a href="http://www.rsyslog.com/doc-rsyslog_conf_examples.html"&gt;Examples&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-5950634626513999862?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/5950634626513999862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=5950634626513999862' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5950634626513999862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5950634626513999862'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2010/01/mysql-reporting-to-syslog.html' title='MySQL reporting to syslog'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-3611930084703237663</id><published>2009-12-30T14:00:00.005+01:00</published><updated>2009-12-31T06:58:26.333+01:00</updated><title type='text'>My wish for the New Year: MySQL DBA's, please install iostat on your servers!</title><content type='html'>Iostat is a very handy tool to help you investigating what kind of performance problems you have. Especially your databases can cause a lot of troubles to your I/O system and thus it would be very nice if every DBA has installed iostat on all of his MySQL database servers.&lt;br /&gt;&lt;br /&gt;Unfortunately most of the Linux distributions do NOT install iostat by default. This causes often unfortunate situations when you are in a MySQL consulting engagement or have a MySQL support case and ask the customer for the output of iostat. In some cases they are not willing or allowed to install iostat on their production systems on the fly (even though I never have seen it causing troubles during or after the installation).&lt;br /&gt;&lt;br /&gt;Further iostat is also not too easy to find because is is hidden in the sysstat package. But iostat can be easily post-installed as follows:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;  shell&amp;gt; sudo apt-get install sysstat&lt;br /&gt;  shell&amp;gt; yum install sysstat&lt;br /&gt;  shell&amp;gt; rpm -i sysstat-&amp;lt;version&amp;gt;.rpm&lt;br /&gt;  shell&amp;gt; dpkg -i sysstat-&amp;lt;version&amp;gt;.deb&lt;br /&gt;  shell&amp;gt; emerge -avq sysstat&lt;br /&gt;  shell&amp;gt; ./configure ; make ; make install&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;So my second wish for the New Year is: Linux distributions, please add sysstat to the default installation/base packages!&lt;br /&gt;&lt;br /&gt;My preferred way running iostat is:&lt;br /&gt;&lt;br /&gt;&lt;code&gt;  shell&amp;gt; iostat -kx 1&lt;/code&gt;&lt;br /&gt;&lt;br /&gt;More about what iostat tells you later on this channel...&lt;br /&gt;&lt;br /&gt;For more details go here:&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://pagesperso-orange.fr/sebastien.godard/"&gt;sysstat&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://pagesperso-orange.fr/sebastien.godard/man_iostat.html"&gt;iostat man pages&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-3611930084703237663?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/3611930084703237663/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=3611930084703237663' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3611930084703237663'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3611930084703237663'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2009/12/my-wish-for-new-year-mysql-dbas-please.html' title='My wish for the New Year: MySQL DBA&apos;s, please install iostat on your servers!'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-2613060430290170272</id><published>2009-10-19T10:14:00.003+02:00</published><updated>2009-10-19T10:23:12.297+02:00</updated><title type='text'>MySQL useful add-on collection using UDF</title><content type='html'>I really like this new toy (for me) called UDF. So I try to provide some more, hopefully useful, functionality.&lt;br /&gt;&lt;br /&gt;The newest extension I like is the possibility to write to the MySQL error log through the application. Oracle can do that since long. Now we can do this as well...&lt;br /&gt;&lt;br /&gt;A list of what I have done up to now you can find here:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt; &lt;li&gt;Query and change InnoDB spin_wait_delay: &lt;a href="http://www.shinguz.ch/MySQL/udf_spin_wait_delay-5.1.30-linux-i686-glibc23.so"&gt;udf_spin_wait_delay-5.1.30-linux-i686-glibc23.so&lt;/a&gt; (md5 807c6bc09b5dc88a8005788519f2483a)&lt;/li&gt;&lt;br /&gt; &lt;li&gt;Send message to the MySQL error log: &lt;a href="http://www.shinguz.ch/MySQL/udf_log_error-5.1.30-linux-i686-glibc23.so"&gt;udf_log_error-5.1.30-linux-i686-glibc23.so&lt;/a&gt; (md5 dc8ef3e91cf6dec84ab3ad95626ec9b5)&lt;/li&gt;&lt;br /&gt; &lt;li&gt;...&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;If you have some more suggestions, please let me know.&lt;br /&gt;&lt;br /&gt;The complete details you can find &lt;a href="http://www.shinguz.ch/MySQL/mysql-useful-udf-collection.html" target="_blank"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-2613060430290170272?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/2613060430290170272/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=2613060430290170272' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2613060430290170272'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2613060430290170272'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2009/10/mysql-useful-add-on-collection-using.html' title='MySQL useful add-on collection using UDF'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-5002366727101574371</id><published>2009-10-15T19:34:00.006+02:00</published><updated>2009-10-19T09:24:55.378+02:00</updated><title type='text'>Using MySQL User-Defined Functions (UDF) to get MySQL internal informations</title><content type='html'>In one of my previous posts I was writing about how to read other processes memory [&lt;a href="http://shinguz.blogspot.com/2009/08/reading-other-processes-memory.html" target="_blank"&gt;1&lt;/a&gt;]. As an example I tried to get the value of the hard coded MySQL internal InnoDB variable spin_wait_delay (srv_spin_wait_delay).&lt;br /&gt;&lt;br /&gt;In this example we were using gdb or the operating system ptrace function to retrieve this value. This method has the disadvantage that it is pretty invasive.&lt;br /&gt;&lt;br /&gt;When I was working on a customer support case I had the idea to solve this by the much less invasive method of User-Defined Functions (UDF).&lt;br /&gt;&lt;br /&gt;UDF were introduced in MySQL 5.0 [&lt;a href="http://dev.mysql.com/doc/refman/5.1/en/adding-udf.html" target="_blank"&gt;2&lt;/a&gt;]. They provide the feasibility to enlarge the MySQL functionality by adding external code.&lt;br /&gt;&lt;br /&gt;The clue is now that you also can use this external code to do some MySQL internal stuff.&lt;br /&gt;&lt;br /&gt;My idea was now, instead of using gdb/ptrace to get the value of spin_wait_delay, to write and UDF to get and set this value.&lt;br /&gt;&lt;br /&gt;More details about the UDF itself, how to compile and load it you can find on my website [&lt;a href="http://www.shinguz.ch/MySQL/mysql-using-udf-to-get-internal-information.html" target="_blank"&gt;3&lt;/a&gt;].&lt;br /&gt;&lt;br /&gt;Then the UDF has to be loaded and activated in the database:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;mysql&gt; CREATE FUNCTION spin_wait_delay RETURNS INTEGER SONAME "udf_spin_wait_delay.so";&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;To remove the UDF again you can use the following command:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;mysql&gt; DROP FUNCTION spin_wait_delay;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;To check if an UDF is installed or to see which ones are installed the following command gives you the right answer:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;mysql&gt; SELECT * FROM mysql.func;&lt;br /&gt;+-----------------+-----+------------------------+----------+&lt;br /&gt;|&amp;nbsp;name&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;ret&amp;nbsp;|&amp;nbsp;dl&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&amp;nbsp;type&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;|&lt;br /&gt;+-----------------+-----+------------------------+----------+&lt;br /&gt;|&amp;nbsp;spin_wait_delay&amp;nbsp;|&amp;nbsp;&amp;nbsp;&amp;nbsp;2&amp;nbsp;|&amp;nbsp;udf_spin_wait_delay.so&amp;nbsp;|&amp;nbsp;function&amp;nbsp;|&lt;br /&gt;+-----------------+-----+------------------------+----------+&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;When the UDF is compiled and properly loaded into the database you can get the value of spin_wait_delay as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;mysql&gt; SELECT spin_wait_delay();&lt;br /&gt;+--------------------+&lt;br /&gt;| spin_wait_delay(5) |&lt;br /&gt;+--------------------+&lt;br /&gt;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;5 |&lt;br /&gt;+--------------------+&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;And now the real nice thing is that you can even set this value as follows:&lt;br /&gt;&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;mysql&gt; SELECT sping_wait_delay(8);&lt;br /&gt;+--------------------+&lt;br /&gt;| spin_wait_delay(8) |&lt;br /&gt;+--------------------+&lt;br /&gt;|&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;8 |&lt;br /&gt;+--------------------+&lt;br /&gt;&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;With this function we can make a static hard coded InnoDB value dynamically changeable. To make it permanent also after a database restart possibly the functionality of init_file could help you further [&lt;a href="http://dev.mysql.com/doc/refman/5.1/en/server-options.html#option_mysqld_init-file" target="_blank"&gt;4&lt;/a&gt;].&lt;br /&gt;&lt;br /&gt;With this concept we can think about implementing many missing things without touching the MySQL code itself or recompiling MySQL. Please let me know what is missing in your opinion and I can try to implement it. Because I am not a programer the help of those guys would be very appreciated.&lt;br /&gt;&lt;br /&gt;If anybody sees a problem with this method please let me know. I do not know about such things like thread safe and mutexes etc. But I think at least reading should not harm.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Caution&lt;/span&gt;: When you have a crash in your UDF the whole MySQL server will crash. So be careful and test it intensively!&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;Binary&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.shinguz.ch/MySQL/udf_spin_wait_delay-5.1.30-linux-i686-glibc23.so"&gt;udf_spin_wait_delay.so&lt;/a&gt; (md5 807c6bc09b5dc88a8005788519f2483a)&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;/span&gt;&lt;br /&gt;&lt;/href="#l3"&gt;&lt;/href="#l2"&gt;&lt;/href="#l1"&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-5002366727101574371?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/5002366727101574371/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=5002366727101574371' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5002366727101574371'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5002366727101574371'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2009/10/using-mysql-user-defined-functions-udf.html' title='Using MySQL User-Defined Functions (UDF) to get MySQL internal informations'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-6529401390547308307</id><published>2009-10-02T10:24:00.004+02:00</published><updated>2009-10-02T10:41:20.078+02:00</updated><title type='text'>Determine in MySQL if we are in summer time or winter time (daylight saving time, DST)</title><content type='html'>Recently a colleague at Sun was asking me if MySQL can tell him to determine if we are currently in summer time or winter time. He was doing some data analysis of his house where he has installed solar panels.&lt;br /&gt;&lt;br /&gt;I am not aware of what he wants to do exactly, but possibly he wants all the data in solar time. So UTC could help him because UTC does not change much over time.&lt;br /&gt;&lt;br /&gt;Next thing which came to my mind is, that possibly the good place to do such math calculations is the application code and not the database.&lt;br /&gt;&lt;br /&gt;But never the less I was interested in how to solve this IN the database.&lt;br /&gt;&lt;br /&gt;By default your MySQL server relies on your servers time zone. [1]&lt;br /&gt;&lt;br /&gt;So if your server is set-up correctly you should be capable to determine if you are in summer time or winter time by your current time, UTC time and the offset you have to UTC.&lt;br /&gt;&lt;blockquote&gt;  mysql&gt; SELECT IF(ROUND(TIME_TO_SEC(SUBTIME(TIME(SYSDATE()), UTC_TIME())) / 3600, 0) = 2, 'summer time', 'winter time') AS time;&lt;/blockquote&gt;Have fun calculating how much power is produced by your solar panels according to winter or sumer time...&lt;br /&gt;&lt;br /&gt;If you have smarter solutions please let me know.&lt;br /&gt;&lt;br /&gt;[1] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/time-zone-support.html" target="_blank"&gt;Time zone support&lt;/a&gt;&lt;br /&gt;[2] &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html" target="_blank"&gt;Date and time functions&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-6529401390547308307?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/6529401390547308307/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=6529401390547308307' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6529401390547308307'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6529401390547308307'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2009/10/determine-in-mysql-if-we-are-in-summer.html' title='Determine in MySQL if we are in summer time or winter time (daylight saving time, DST)'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-3636478186779315374</id><published>2009-08-14T13:50:00.004+02:00</published><updated>2009-10-02T11:21:37.729+02:00</updated><title type='text'>Reading other processes memory</title><content type='html'>As you probably have experienced yet MySQL does not always provide all internal information as you might want to have them and as you are used to have from other RDBMS.&lt;br /&gt;&lt;br /&gt;MySQL plans to improve this implementing the/a performance schema and its probably already partly done in MySQL 5.4. But who knows when this will be finished and what it contains at all...&lt;br /&gt;&lt;br /&gt;What is not provided to me I want to gather myself... But how? Other RDBMS provide interfaces to attach applications directly to their memory to retreive information. But MySQL does not. So I was looking for a way to read an other process memory.&lt;br /&gt;&lt;br /&gt;I have no clue about programming and thus changing MySQL code was out of focus. Further I am looking for a solution you can use immediately on a running systems at consulting gigs. Some tries to read /proc/&amp;lt;pid&amp;gt;/mem with a little php script failed.&lt;br /&gt;&lt;br /&gt;An article by Domas M. helped me. I do not have to write something myself I can use a tool already exsting to do the work. But gdb is not installed on every machine and usually not at all on production machines. Further gdb is probably an overkill to just read memory of other processes.&lt;br /&gt;&lt;br /&gt;But an other application to do this job I did not find. I just found some comments that ptrace is the way to do it. Ptrace (man ptrace) is not a program (as for example strace) but an operating system function call.&lt;br /&gt;&lt;br /&gt;When you are interested how I found out how to do it please continue reading &lt;a href="http://www.shinguz.ch/MySQL/reading-other-processes-memory.html" target="_blank"&gt;here&lt;/a&gt;.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-3636478186779315374?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/3636478186779315374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=3636478186779315374' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3636478186779315374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3636478186779315374'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2009/08/reading-other-processes-memory.html' title='Reading other processes memory'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-9064720698344658257</id><published>2008-12-23T12:03:00.004+01:00</published><updated>2008-12-23T13:07:57.048+01:00</updated><title type='text'>MySQL licenses for dummies</title><content type='html'>The following summary shows my personal understanding of MySQL 5.1 licenses, packages and products. It does not necessarily reflect 100% the way MySQL understands it. But after all the discussions I hope it is as close as possible to the reality:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MySQL Embedded Database Server&lt;/span&gt; (Download: enterprise.mysql.com -&gt; OEM Software)&lt;br /&gt;Classic (OEM license, -MEM -InnoDB)&lt;br /&gt;Pro (= Classic +InnoDB)&lt;br /&gt;Advanced (= Pro +Partitioning)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MySQL Community Sever&lt;/span&gt; (Download: www.mysql.com -&gt; Downloads)&lt;br /&gt;Community (GPL, -NDB)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MySQL Enterprise Server&lt;/span&gt; (Download: enterprise.mysql.com -&gt; Enterprise Software)&lt;br /&gt;Pro (GPL or commercial, -NDB +InnoDB +MEM, Basic + Silver customer, MRU + QSP)&lt;br /&gt;Advanced (= Pro +Partitioning, Gold + Platinum customer)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;MySQL Cluster&lt;/span&gt; (Download: http://dev.mysql.com/downloads/cluster/)&lt;br /&gt;Community Edition (GPL, all features)&lt;br /&gt;Com (ex CGE?) (OEM or commercial, -InnoDB +NDB)&lt;br /&gt;Com-Pro (Com, all features)&lt;br /&gt;Standard Edition (= Com, -NDB-API -Cluster-Repl, -LDAP)&lt;br /&gt;&lt;/pre&gt;&lt;h2&gt;Upgrade&lt;/h2&gt;EP customer should follow the QSP trail unless it is critical for them to install an MRU to get a quick bugfix to hold them over until the next QSP is released.&lt;pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Month   version / release&lt;/span&gt;&lt;br /&gt;    0   5.1.30&lt;br /&gt;    1   5.1.30-MRU1&lt;br /&gt;    2   5.1.30-MRU2&lt;br /&gt;    3   5.1.31&lt;br /&gt;    4   5.1.31-MRU1 and 5.1.30-QSP&lt;br /&gt;    5   5.1.31-MRU2&lt;br /&gt;    6   5.1.32&lt;br /&gt;    7   5.1.32-MRU1 and 5.1.31-QSP&lt;/pre&gt;&lt;h2&gt;Legend&lt;/h2&gt;&lt;pre&gt;CE  - Community Edition&lt;br /&gt;EP  - Enterprise Edition (why not EE?)&lt;br /&gt;MRU - Monthly Rapid Update (EP only)&lt;br /&gt;QSP - Quarterly Service Pack (EP only)&lt;br /&gt;OEM - Original Equipment Manufacturer&lt;br /&gt;MEM - MySQL Enterprise Monitior&lt;br /&gt;CGE - Carrier Grade Edition&lt;br /&gt;&lt;/pre&gt;Please correct me, if I am wrong. And when you have more questions let me know and I try to clear this.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-9064720698344658257?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/9064720698344658257/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=9064720698344658257' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/9064720698344658257'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/9064720698344658257'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/12/mysql-licenses-for-dummies.html' title='MySQL licenses for dummies'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-66668890045988237</id><published>2008-11-13T21:43:00.008+01:00</published><updated>2009-08-14T09:52:42.772+02:00</updated><title type='text'>Why does MySQL Cluster takes so long for --initial?</title><content type='html'>This week we had a very interesting problem at a customer: They complained, that their MySQL Cluster takes about 1 hour for a --initial start-up. After some tuning on the hardware and the config.ini they brought it down to around 40 minutes. But this is still unacceptable long...&lt;br /&gt;&lt;br /&gt;This sounds a little strange to me. But let us have a look at their config.ini first. It looked more or less like the following (which is already tuned!):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# config.ini&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[NDB_MGMD DEFAULT]&lt;br /&gt;DataDir                      = /localdisk/cluster&lt;br /&gt;&lt;br /&gt;[NDBD DEFAULT]&lt;br /&gt;DataDir                      = /localdisk/cluster&lt;br /&gt;NoOfReplicas                 =     2&lt;br /&gt;LockPagesInMainMemory        =     1&lt;br /&gt;DataMemory                   = 12000M&lt;br /&gt;IndexMemory                  =  2000M&lt;br /&gt;&lt;br /&gt;FragmentLogFileSize          =   256M&lt;br /&gt;NoOfFragmentLogFiles         =    42&lt;br /&gt;&lt;br /&gt;DiskCheckpointSpeedInRestart =   100M&lt;br /&gt;ODirect                      =     1&lt;br /&gt;&lt;br /&gt;BackupMaxWriteSize           =     1M&lt;br /&gt;BackupDataBufferSize         =    16M&lt;br /&gt;BackupLogBufferSize          =     4M&lt;br /&gt;BackupMemory                 =    20M&lt;br /&gt;&lt;br /&gt;[NDB_MGMD]&lt;br /&gt;id                           =     1&lt;br /&gt;hostname                     = 192.168.0.1&lt;br /&gt;&lt;br /&gt;[NDBD]&lt;br /&gt;id                           =    10&lt;br /&gt;hostname                     = 192.168.0.10&lt;br /&gt;&lt;br /&gt;[NDBD]&lt;br /&gt;id                           =    11&lt;br /&gt;hostname                     = 192.168.0.11&lt;br /&gt;&lt;br /&gt;[MYSQLD]&lt;br /&gt;[MYSQLD]&lt;br /&gt;[MYSQLD]&lt;br /&gt;[MYSQLD]&lt;br /&gt;[MYSQLD]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So the config.ini looks fine. But why does it take so long? Let us have a look who is the evil guy:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# grep phase ndb_1_cluster.log | grep "Node 10"&lt;br /&gt;&lt;br /&gt;2008-10-24 12:24:16 [MgmSrvr] INFO     -- Node 10: Start phase 1 completed&lt;br /&gt;2008-10-24 12:24:16 [MgmSrvr] INFO     -- Node 10: Start phase 2 completed (initial start)&lt;br /&gt;2008-10-24 12:24:16 [MgmSrvr] INFO     -- Node 10: Start phase 3 completed (initial start)&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;2008-10-24 13:03:03 [MgmSrvr] INFO     -- Node 10: Start phase 4 completed (initial start)&lt;/span&gt;&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 5 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 6 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 7 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 8 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 9 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 100 completed (initial start)&lt;br /&gt;2008-10-24 13:03:08 [MgmSrvr] INFO     -- Node 10: Start phase 101 completed (initial start)&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Start phase 4 is the one! But what is start phase 4? According to the &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-start-phases.html"&gt;MySQL Cluster documentation&lt;/a&gt; start phase 4 means:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-weight: bold;"&gt;Phase 4.&lt;/span&gt;   For an initial start or initial node restart, the redo log files are created. The number of these files is equal to NoOfFragmentLogFiles.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Creating the redo log files is the problem! I have never created a MySQL Cluster with 42 Gbyte of redo log file (42 x 4 x 256Mbyte) myself so I have no practical experience with it how long it should take.&lt;br /&gt;&lt;br /&gt;What I did first was a rough calculation of the value I would expect:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;43'008 Mbyte : 50 Mbyte/s = 860 s = 15 minutes&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;After 15 minutes I would expect the cluster to be up and running (plus some seconds for the other phases). What I expect seems not to be the same as what happens... :(&lt;br /&gt;&lt;br /&gt;I turned on iostat (by the way: IMHO iostat (sysstat packages) belongs on every server which does some kind of I/O!):&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# iostat -x 1&lt;br /&gt;&lt;br /&gt;avg-cpu:  %user   %nice %system %iowait  %steal   %idle&lt;br /&gt;          0.00    0.00    0.12   18.35    0.00   81.52&lt;br /&gt;&lt;br /&gt;Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util&lt;br /&gt;sda          0.00 193.00  0.00 55.00    0.00 2016.00     0.00  1008.00    36.65     2.13   38.55  18.18 100.00&lt;br /&gt;&lt;br /&gt;avg-cpu:  %user   %nice %system %iowait  %steal   %idle&lt;br /&gt;          0.00    0.00    0.25   18.88    0.00   80.88&lt;br /&gt;&lt;br /&gt;Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util&lt;br /&gt;sda          0.00 192.00  0.00 48.00    0.00 2088.00     0.00  1044.00    43.50     1.72   35.50  20.83 100.00&lt;br /&gt;&lt;br /&gt;avg-cpu:  %user   %nice %system %iowait  %steal   %idle&lt;br /&gt;          0.00    0.00    0.00   19.12    0.00   80.88&lt;br /&gt;&lt;br /&gt;Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util&lt;br /&gt;sda          0.00 200.00  0.00 47.00    0.00 2088.00     0.00  1044.00    44.43     1.69   35.91  21.28 100.00&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OK. As we can see, the I/O device is fully utilized. Good to know. Looks like we have an I/O problem! We do only around 50 w/s which is really bad (normal disks can do around 150 - 250 w/s) and we write with a throughput of 1 MByte/s (is about 20 kbyte/write) instead of 50 Mbyte/s.&lt;br /&gt;&lt;br /&gt;What came to my mind is, that earlier this year I have written an article about &lt;a href="http://www.shinguz.ch/MySQL/mysql_sparse_files.html"&gt;Sparse files&lt;/a&gt;. I found then, that MySQL Cluster writes the redo log files as sparse files to disk. Could this have an impact? But we have never had any complains about this from other customers...&lt;br /&gt;&lt;br /&gt;So what I did next: I tried on a completely different hardware from an other vendor and it took only 13 minutes! The problem seems to be NOT MySQL Cluster (alone) related! On our machines we have also an NFS mount. So let us try there: Even worse: 10 minutes! Then we did a synthetical test on the hardware:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# dd if=/dev/zero of=redo_log.42g count=0 obs=1 seek=42G&lt;br /&gt;# dd if=/dev/zero of=redo_log.42g bs=32K count=1376256 of=direct&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This was running in 12 minutes! I was confused. Maybe my simulation has to be more complex:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#!/bin/bash&lt;br /&gt;&lt;br /&gt;let i=1&lt;br /&gt;# 1376256&lt;br /&gt;while [[ $i -le  ]] ; do&lt;br /&gt; dd if=/dev/zero of=big_file.42g obs=512 count=1 seek=32K&lt;br /&gt; let i=$i+1&lt;br /&gt;done&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;No results which come close to the thing I have seen from MySQL Cluster...&lt;br /&gt;&lt;br /&gt;Let us summarize:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;Our servers with Mysql Cluster:  37 minutes&lt;br /&gt;Test servers with Mysql Cluster: 13 minutes&lt;br /&gt;Our servers with dd:             12 minutes&lt;br /&gt;Our servers with NFS:            10 minutes&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This does not make sense to me. I need the PERFECT simulation!&lt;br /&gt;&lt;br /&gt;For knowing more, how the redo log files were created I run a trace on the ndbd process during the creation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# strace -o ndbd.trace -ff -s 128 -p &lt;ndbd_pid&gt;&lt;br /&gt;&lt;/ndbd_pid&gt;&lt;/pre&gt;&lt;br /&gt;As a result I got this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;open("/localdisk/cluster/ndb_11_fs/D10/DBLQH/S3.FragLog", O_RDWR|O_CREAT|O_TRUNC|O_DIRECT, 0666) = 17&lt;br /&gt;lseek(17, 268402688, SEEK_SET) = 268402688   # 256M - 32k&lt;br /&gt;write(17, "..."..., 32768) = 32768&lt;br /&gt;fsync(17)                         = 0&lt;br /&gt;lseek(17, 0, SEEK_SET) = 0&lt;br /&gt;write(17, "..."..., 32768) = 32768&lt;br /&gt;fsync(17)                         = 0&lt;br /&gt;lseek(17, 1048576, SEEK_SET) = 1048576&lt;br /&gt;write(17, ""..., 32768) = 32768&lt;br /&gt;fsync(17)                         = 0&lt;br /&gt;lseek(17, 2097152, SEEK_SET) = 2097152&lt;br /&gt;write(17, ""..., 32768)= 32768&lt;br /&gt;fsync(17)                         = 0&lt;br /&gt;&lt;br /&gt;...&lt;br /&gt;lseek(17, 267386880, SEEK_SET) = 267386880&lt;br /&gt;write(17, ""..., 32768)                         = 32768&lt;br /&gt;fsync(17) = 0&lt;br /&gt;close(17) = 0&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;OK. I see, my simulation up to now was not yet good enough... I need a Perl script to simulate this more exactly. The script you can find here: &lt;a href="http://www.shinguz.ch/MySQL/consulting_tools.html#cluster_initial_test"&gt;cluster_initial_test.pl&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Before I run the script I was pretty nervous: Would it work? But after a few minutes it was already clear: It has the wanted effect. After around 1/3 of the redo log files were created I estimated the end time to 59 minutes and when it ended it took around 50 minutes. Perfect!&lt;br /&gt;&lt;br /&gt;After I came back from a short jig I was thinking about why it took longer than 40 minutes... What I can see from the system statistics is, that the I/O system is more relaxed with my script than with the original MySQL Cluster --initial restart.&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;# iostat -x 1&lt;br /&gt;&lt;br /&gt;Device:    rrqm/s wrqm/s   r/s   w/s  rsec/s  wsec/s    rkB/s    wkB/s avgrq-sz avgqu-sz   await  svctm  %util&lt;br /&gt;sda          0.00 161.39  0.00 49.50    0.00 1798.02     0.00   899.01    36.32     1.05   20.40  14.32  70.89&lt;br /&gt;sda          0.00 176.00  0.00 51.00    0.00 1920.00     0.00   960.00    37.65     1.07   21.18  14.04  71.60&lt;br /&gt;sda          0.00 170.71  0.00 46.46    0.00 1882.83     0.00   941.41    40.52     0.99   21.22  15.74  73.13&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So it is about 25-33% less utilized. MySQL Cluster creates the redo log files with 4 threads in parallel. For me this is a sufficient exact explanation for the moment why it takes longer.&lt;br /&gt;&lt;br /&gt;We are able to decouple now the hardware problem from the software product. I cannot really help the hardware guys to solve their problem, but at least we were able to give them a simulation of the problem. So they can run the tests without us.&lt;br /&gt;&lt;br /&gt;On the other hand MySQL Cluster is doing exactly what I always tell my customers not to do: "COMMIT after every INSERT". This is the worst thing what you can do with an I/O system. MySQL Cluster does a sync to disk after every 32k block (1 block per Mbyte).&lt;br /&gt;So I was talking to &lt;a href="http://jonasoreland.blogspot.com/"&gt;Jonas&lt;/a&gt;, one of our MySQL Cluster developers, and told him the whole story. He was just asking me: "Is 14:00 early enough for the patch?"&lt;br /&gt;&lt;br /&gt;Before 14:00 I had already the patch in my mailbox. We applied it and tested it and...&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;span style="font-weight: bold;font-size:180%;" &gt;5 minutes 12 seconds!&lt;/span&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;So I think now everybody should be happy?&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Addendum:&lt;/h2&gt;&lt;ul&gt;&lt;li&gt;The perl script could be improved by:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;sysopen(HANDLE, $path, O_RDWR|O_CREAT|O_EXCL|O_DIRECT) or die "sysopen $path: $!";&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;Maybe the problem could be also simulated much easier with dd like this:&lt;/li&gt;&lt;/ul&gt;&lt;pre&gt;# dd if=/dev/zero of=redo_log.42g bs=1M count=43008 of=direct conv=fsync&lt;/pre&gt;&lt;ul&gt;&lt;li&gt;You can find the patch here: &lt;a href="http://bugs.mysql.com/bug.php?id=40734"&gt;Bug #40734&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-66668890045988237?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/66668890045988237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=66668890045988237' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/66668890045988237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/66668890045988237'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/11/why-does-mysql-cluster-takes-so-long.html' title='Why does MySQL Cluster takes so long for --initial?'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-322936098434328736</id><published>2008-10-13T15:17:00.003+02:00</published><updated>2008-10-13T15:32:05.012+02:00</updated><title type='text'>MySQL Multi-Master – Single-Slave – Replication (Episode 2)</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Introduction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One of the features that make MySQL so great is its easy replication set-up. If you are experienced and know-how to do it, it takes you about 15 minutes to set-up a slave. What you have in the end is a replication from one master to one or several slaves. So you can build a top-down data stream pyramid and spread your data on many slaves.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://1.bp.blogspot.com/_p9iYKIS3iFI/SPNKuAiLG4I/AAAAAAAAAAg/og35RRxmJNM/s1600-h/mm-single-slave-repl_2a.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://1.bp.blogspot.com/_p9iYKIS3iFI/SPNKuAiLG4I/AAAAAAAAAAg/og35RRxmJNM/s320/mm-single-slave-repl_2a.png" alt="" id="BLOGGER_PHOTO_ID_5256627344349272962" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;From time to time some customers are asking for the other way: Many masters replicating to one slave (which is also called multi-source replication). For this requirement MySQL replication cannot help you directly.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Possibilities&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You can circumvent this situation in the following ways:&lt;br /&gt;&lt;ol&gt;&lt;br /&gt;&lt;li&gt;Implement your own data transfer mechanism.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Use this ugly hack I have written down 2 years ago: &lt;a href="http://www.shinguz.ch/MySQL/mm-single-slave-repl.pdf" target="_blank"&gt;Multi-Master-Single-Slave-Replication&lt;/a&gt;&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Test the approach described in the following article.&lt;/li&gt;&lt;br /&gt;&lt;li&gt;Wait until MySQL has implemented it...&lt;/li&gt;&lt;br /&gt;&lt;/ol&gt;&lt;br /&gt;Possibility number 4 for would be the nicest one. Because then the solution would be properly supported by your database vendor and you do not have to take care much about problems, as long as you have a support contract.&lt;br /&gt;&lt;br /&gt;When we look at the &lt;a href="http://forge.mysql.com/worklog/" target="_blank"&gt;MySQL work log&lt;/a&gt; and search for &lt;span style="font-style:italic;"&gt;replication&lt;/span&gt; we find a work log entry with the title: &lt;a href="http://forge.mysql.com/worklog/task.php?id=1697" target="_blank"&gt;WL#1697: Multi-source replication&lt;/a&gt;. But for whatever reason it has the following status: &lt;span style="font-style:italic;"&gt;Affects: Server-7.0 — Status: On-Hold — Priority: Low&lt;/span&gt;. :-(&lt;br /&gt;&lt;br /&gt;What can we do now:&lt;br /&gt;a) Resign.&lt;br /&gt;b) Become an important customer (by paying much money), complain about the priority and if nothing changes escalate it to the top management of MySQL.&lt;br /&gt;c) Find many many other fellow sufferers, unite and make your database vendors management aware of your desire.&lt;br /&gt;d) Help yourself (it is eventually an Open Source product...).&lt;br /&gt;&lt;br /&gt;Possibilities number 1 to 3 from above are some kind of &lt;span style="font-style:italic;"&gt;Help yourself&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Help yourself&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Because I am not a programmer and I have no clue about programming, possibility number 1 is out of question for me. But I am sure there are many other MySQL users out there in the world which would appreciate your effort.&lt;br /&gt;Possibility number 2 is a quick and ugly hack but may work in some situations.&lt;br /&gt;And number 3 I was pointed to by a user called Kwame who wrote me an email (thanks Kwame for the cool hint!).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;A possible solution&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;One and a half year ago I wrote down a little article about &lt;a href="http://www.shinguz.ch/MySQL/external_locking.html" target=""&gt;MySQL Active - Active Clustering"&lt;/a&gt; because we had ever and ever customer asking for a replacement for a well known but very expensive product from an other big database vendor.&lt;br /&gt;Peter Zaitsev was not very happy with the content of it: &lt;a href="http://www.mysqlperformanceblog.com/2007/03/15/mysql-myisam-active-active-clustering-looking-for-trouble/" target="_blank"&gt;MySQL MyISAM Active Active Clustering - looking for trouble?&lt;/a&gt;. But comments about the critics already gave a sign for the solution: When you combine the MySQL Active-Active Clustering with MySQL replication you can finally get a many-master single slave replication!&lt;br /&gt;&lt;br /&gt;So what I did was the following:&lt;br /&gt;&lt;br /&gt;I have 3 servers which act as a master and on the 4th server I install 3 MySQL instances (mysqld) running on the same datadir. Please make sure, that you replicate ONLY ONE SCHEMA per master slave pair!&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/_p9iYKIS3iFI/SPNL8qAC83I/AAAAAAAAAAo/CEQLLxMOeh4/s1600-h/mm-single-slave-repl_2.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_p9iYKIS3iFI/SPNL8qAC83I/AAAAAAAAAAo/CEQLLxMOeh4/s320/mm-single-slave-repl_2.png" border="0" alt=""id="BLOGGER_PHOTO_ID_5256628695510217586" /&gt;&lt;/a&gt;&lt;br /&gt;As configuration file for my slaves I have used something like this:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;#&lt;br /&gt;# my.cnf&lt;br /&gt;#&lt;br /&gt;&lt;br /&gt;[mysqld]&lt;br /&gt;&lt;br /&gt;port          = 3308&lt;br /&gt;socket        = /home/mysql/tmp/mysql-3308.sock&lt;br /&gt;pid-file      = /home/mysql/data/mysqld5127/mysql-3308.pid&lt;br /&gt;datadir       = /home/mysql/data/mysqld5127&lt;br /&gt;&lt;br /&gt;skip-innodb&lt;br /&gt;external-locking&lt;br /&gt;log-error     = /home/mysql/data/mysqld5127/error_4.log&lt;br /&gt;&lt;br /&gt;server_id           = 4&lt;br /&gt;master-info-file    = /home/mysql/data/mysqld5127/master.info&lt;br /&gt;relay-log           = /home/mysql/data/mysqld5127/mysql-3308-relay-bin&lt;br /&gt;relay-log-index     = /home/mysql/data/mysqld5127/mysql-3308-relay-bin&lt;br /&gt;relay-log-info-file = /home/mysql/data/mysqld5127/relay-log.info&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight:bold;"&gt;Requirements&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Make sure that:&lt;br /&gt;&lt;ul&gt;&lt;br /&gt;&lt;li&gt;You only write to one schema per master (schema_a in master 1, schema_b in master 2 and so on...)&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You comply with all the requirements described in the document MySQL Active - Active Clustering&lt;/li&gt;&lt;br /&gt;&lt;li&gt;You flush the tables on ALL slave before reading.&lt;/li&gt;&lt;br /&gt;&lt;/ul&gt;&lt;br /&gt;Very simple first tests showed, that it is possible to "aggregate" the data from many masters into a single slave. But please verify this proof of concept very carefully before you deploy it to your productive system with your real data. This approach is neither recommended nor supported by MySQL.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Drawback&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;A further replication from this slave system to other slaves is not possible (or at least no feasible solution comes to my mind) except you use MySQL cluster as "aggregator". Then it could be possible...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-322936098434328736?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/322936098434328736/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=322936098434328736' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/322936098434328736'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/322936098434328736'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/10/mysql-multi-master-single-slave.html' title='MySQL Multi-Master – Single-Slave – Replication (Episode 2)'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_p9iYKIS3iFI/SPNKuAiLG4I/AAAAAAAAAAg/og35RRxmJNM/s72-c/mm-single-slave-repl_2a.png' height='72' width='72'/><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-6420637327982143214</id><published>2008-10-09T15:25:00.002+02:00</published><updated>2008-10-09T15:28:14.574+02:00</updated><title type='text'>Test application for MySQL high availability (HA) set-up</title><content type='html'>When I set-up a MySQL HA environment for customers I usually do some final fail over tests after configuring the whole beast.&lt;br /&gt;&lt;br /&gt;To check if the application behaves like expected I always run my little test application (&lt;a href="http://www.shinguz.ch/MySQL/consulting_tools.html#ha_test"&gt;test.sh&lt;/a&gt;) from the server(s) where the customers application runs. It displays "graphically" how the application behaves and you can show to the customer immediately what is going on...&lt;br /&gt;&lt;br /&gt;Make sure, that you point it to the VIP (virtual IP) or the LB (load balancer).&lt;br /&gt;&lt;br /&gt;It was really useful for me and I recommend you to do your HA fail over tests also at least with this little tool to avoid evil surprises in the future.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-6420637327982143214?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/6420637327982143214/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=6420637327982143214' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6420637327982143214'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6420637327982143214'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/10/test-application-for-mysql-high.html' title='Test application for MySQL high availability (HA) set-up'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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-6864099895737809960.post-2238889930052133236</id><published>2008-09-25T15:02:00.002+02:00</published><updated>2008-09-25T15:05:55.042+02:00</updated><title type='text'>Citation of the week</title><content type='html'>"Das dreieckige Rad hat gegenüber dem viereckigen einen gewaltigen Vorteil: Ein Rumms weniger pro Umdrehung!"&lt;br /&gt;&lt;br /&gt;Translation:&lt;br /&gt;"The triangular wheel has one enormous advantage over the quadrangular: One knock less per revolution!"&lt;br /&gt;&lt;br /&gt;Maybe not new, but I have not heard it yet and I love it. It was about reinventing functionality in a well known product...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-2238889930052133236?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/2238889930052133236/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=2238889930052133236' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2238889930052133236'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2238889930052133236'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/09/citation-of-week.html' title='Citation of the week'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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-6864099895737809960.post-3307537622217901639</id><published>2008-09-23T16:18:00.005+02:00</published><updated>2008-09-24T11:15:31.524+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='MySQL cluster convert innodb myisam error index file'/><title type='text'>MySQL Cluster: No more room in index file</title><content type='html'>Recently we were migrating an InnoDB/MyISAM schema to NDB. I was too lazy to calculate all the needed MySQL Cluster parameters (for example with &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-utilities-ndb-size.html"&gt;ndb_size.pl&lt;/a&gt;) and just took my default &lt;a href="http://www.shinguz.ch/MySQL/mysql_cluster_overview.html#config_ini"&gt;config.ini&lt;/a&gt; template.&lt;br /&gt;Because I am really lazy I have a little script doing this for me (&lt;a href="http://www.shinguz.ch/MySQL/consulting_tools.html#alter_engine"&gt;alter_engine.sh&lt;/a&gt;).&lt;br /&gt;&lt;br /&gt;But suddenly my euphoria was stopped abruptly by the following error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;MySQL error code 136: No more room in index file&lt;/pre&gt;&lt;br /&gt;The usual command that helps me in such a situation is a follows:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# perror 136&lt;br /&gt;MySQL error code 136: No more room in index file&lt;/pre&gt;&lt;br /&gt;But in this case it is not really helpful. Also&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# perror --ndb 136&lt;/pre&gt;&lt;br /&gt;does not bring us further. Strange: Index file... We are converting from MyISAM/InnoDB to NDB. Why the hell is he using an index file for this operation? It seems to be clearly a mysqld error message and not a MySQL Cluster error message. And we are also not using &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-disk-data.html"&gt;MySQL Cluster disk data tables&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;After bothering a bit &lt;a href="http://www.mysql.com/support/"&gt;MySQL support&lt;/a&gt; I had the idea to do the following:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;# ndb_show_tables | grep -ic orderedindex&lt;br /&gt;127&lt;/pre&gt;&lt;br /&gt;The &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-ndbd-definition.html#mysql-cluster-param-ndbd-definition-maxnooforderedindexes"&gt;MySQL online documentation&lt;/a&gt; clearly states:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;MaxNoOfOrderedIndexes&lt;br /&gt;...&lt;br /&gt;The default value of this parameter is 128.&lt;/pre&gt;&lt;br /&gt;So this could be the reason! When I have changed this parameter followed by the common &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-cluster-rolling-restart.html"&gt;rolling restart&lt;/a&gt; of the MySQL Cluster I could continue to migrate my schema into cluster...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;MySQL errors can be related to cluster errors and do not necessarily point to the source of the problem. The error:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;MySQL error code 136: No more room in index file&lt;/pre&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:130%;" &gt;&lt;br /&gt;means just MaxNoOfOrderedIndexes is too small!&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I hope that I can safe you some time with this little article.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-3307537622217901639?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/3307537622217901639/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=3307537622217901639' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3307537622217901639'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3307537622217901639'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/09/mysql-cluster-no-more-room-in-index.html' title='MySQL Cluster: No more room in index file'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-1729123462621843627</id><published>2008-09-23T13:20:00.006+02:00</published><updated>2008-09-23T13:39:09.375+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql ndb-api memory leak'/><title type='text'>Possible memory leak in NDB-API applications?</title><content type='html'>A customer has recently experienced a possible memory leak in its NDB-API application. What he did was something like&lt;br /&gt;&lt;pre&gt;# ps aux | grep &amp;lt;pid&amp;gt;&lt;/pre&gt;&lt;br /&gt;over time and then he saw the RSS increasing. When he would have had a look a little longer he would have seen that the RSS consumption would increase up to a certain level and then becomes stable. Which is the expected behaviour.&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_p9iYKIS3iFI/SNjRbghGAWI/AAAAAAAAAAM/Hxip6OI7nlM/s1600-h/rss1.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_p9iYKIS3iFI/SNjRbghGAWI/AAAAAAAAAAM/Hxip6OI7nlM/s320/rss1.png" alt="" id="BLOGGER_PHOTO_ID_5249175636215726434" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;But how to explain to the customer that his application, which was in fact not doing anything, consumes more RSS?&lt;br /&gt;With a diff over time on &lt;span style="font-family: courier new;"&gt;/proc/&amp;lt;pid&amp;gt;/smaps&lt;/span&gt; we found that this area was the reason:&lt;br /&gt;&lt;pre&gt;b67b7000-b6fca000 rw-p b67b7000 00:00 0 (8 Mbyte)&lt;br /&gt;Size:               8268 kB&lt;br /&gt;Rss:                 148 kB&lt;br /&gt;Shared_Clean:          0 kB&lt;br /&gt;Shared_Dirty:          0 kB&lt;br /&gt;Private_Clean:         0 kB&lt;br /&gt;Private_Dirty:       148 kB&lt;br /&gt;Referenced:          148 kB&lt;/pre&gt;&lt;br /&gt;But what is this meaning? To find the answer we did a strace on the program and got the following system calls:&lt;br /&gt;&lt;pre&gt;...&lt;br /&gt;read(5, "127.0.0.1 localhost\n\n# The follo"..., 4096) = 450&lt;br /&gt;close(5) = 0&lt;br /&gt;munmap(0xb7acb000, 4096) = 0&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;mmap2(NULL, 2117632, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb69bf000 - 0xB6BC4000 (2068 Mbyte)&lt;br /&gt;mmap2(NULL, 2101248, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb67be000 - 0xb69bf000 (2052 Mbyte)&lt;br /&gt;&lt;/span&gt;mmap2(NULL, 32768, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7ac4000&lt;br /&gt;mprotect(0xb7ac4000, 4096, PROT_NONE) = 0&lt;br /&gt;clone(child_stack=0xb7acb4b4, flags=CLONE_VM|CLONE_FS|CLONE_FILES|CLONE_SIGHAND|CLONE_THREAD|CLONE_SYSVSEM|CLONE_SETTLS|CLONE_PARENT_SETTID|CLONE_C&lt;br /&gt;...&lt;/pre&gt;&lt;br /&gt;OK. Somebody is allocating 2 times 2 junks of about 2 Mbyte of memory. But what the hell could this be??? During night I found the solution. It is the SendBufferMemory and ReceiveBufferMemory which I have configured in the config.ini to that size...&lt;br /&gt;&lt;br /&gt;When you experience similar behaviour on your processes, maybe this little script can help you to find the problem: &lt;a href="http://www.shinguz.ch/MySQL/mem_tracker.sh.txt"&gt;mem_tracker.sh&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;By the way, with an other customer we wound some other nice behaviour. But this time it was a mysqld:&lt;br /&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/_p9iYKIS3iFI/SNjR-GVov3I/AAAAAAAAAAU/tV3g05VVF0s/s1600-h/rss2.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer;" src="http://3.bp.blogspot.com/_p9iYKIS3iFI/SNjR-GVov3I/AAAAAAAAAAU/tV3g05VVF0s/s320/rss2.png" alt="" id="BLOGGER_PHOTO_ID_5249176230483771250" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-1729123462621843627?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/1729123462621843627/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=1729123462621843627' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/1729123462621843627'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/1729123462621843627'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/09/possible-memory-leak-in-ndb-api.html' title='Possible memory leak in NDB-API applications?'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_p9iYKIS3iFI/SNjRbghGAWI/AAAAAAAAAAM/Hxip6OI7nlM/s72-c/rss1.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-5394715872579152552</id><published>2008-09-05T16:00:00.006+02:00</published><updated>2008-09-05T16:23:14.217+02:00</updated><title type='text'>Active/active fail over cluster with MySQL Replication</title><content type='html'>&lt;span style="font-size:180%;"&gt;Electing a slave as new master and aligning the other slaves to the new master&lt;/span&gt;&lt;br /&gt;      &lt;style type="text/css"&gt;  &lt;!--   @page { margin: 2cm }   P { margin-bottom: 0.21cm }  --&gt;  &lt;/style&gt;  &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;In a simple MySQL Replication set-up you have high-availability (HA) on the read side (r). But for the master which covers all the writes (w) and the time critical read (rt) there is no HA implemented. For some situations this can be OK. For example if you have rarely writes or if you can wait until a new Master is set up.&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;But in other cases you need a fast fail-over to a new master.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;In the following article it is shown how to implement the election of a new master and how to align the slaves to the new master.&lt;/p&gt;  &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;&lt;/p&gt;We can have two possible scenarios:            &lt;br /&gt;&lt;ol&gt;&lt;li&gt;This scenario assumes, that every slave can become the new master.           &lt;/li&gt;&lt;li&gt;This scenario assumes, that only one dedicated slave will become master.&lt;/li&gt;&lt;/ol&gt;         &lt;style type="text/css"&gt;  &lt;!--   @page { margin: 2cm }   P { margin-bottom: 0.21cm }  --&gt;  &lt;/style&gt;  &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;The advantages and disadvantages of both scenarios:&lt;/p&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scenario 1&lt;/span&gt;&lt;br /&gt;+ You can choose the slave which is the most actual one.&lt;br /&gt;- Higher possibility of errors if not automatized.&lt;br /&gt;- You do not need an extra spare slave.&lt;br /&gt;- More bin log writing on all Slaves.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Scenario 2&lt;/span&gt;&lt;br /&gt;+ You do not have to choose which is the new master, you already have defined before.&lt;br /&gt;- You have the possibility to not choose the Slave with the most recent data applied.&lt;br /&gt;       &lt;style type="text/css"&gt;  &lt;!--   @page { margin: 2cm }   P { margin-bottom: 0.21cm }  --&gt;  &lt;/style&gt;  &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;&lt;b&gt;Important&lt;/b&gt;: All the slaves which can become master have to run with log-bin on and log-slave-updates.&lt;/p&gt; &lt;p class="western" style="margin-bottom: 0cm;" align="justify"&gt;          &lt;style type="text/css"&gt;  &lt;!--   @page { margin: 2cm }   P { margin-bottom: 0.21cm }   H2 { margin-bottom: 0.21cm }   H2.western { font-family: "Nimbus Sans L", sans-serif; font-size: 14pt; font-style: italic }   H2.cjk { font-size: 14pt; font-style: italic }   H2.ctl { font-size: 14pt; font-style: italic }  --&gt;  &lt;/style&gt;  &lt;/p&gt;&lt;h2 class="western" align="justify"&gt;&lt;/h2&gt;&lt;p&gt;&lt;/p&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-size:130%;"&gt;Electing a Slave to become the new master&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Szenario 1: Compare output of SHOW SLAVE STATUS and decide which one will become the new master.&lt;br /&gt;Szenario 2: Not necessary because it is already done before.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Aligning the other slaves to the new master&lt;/span&gt;&lt;br /&gt;The officially recommended way to set-up again a replication when the master fails is as follows:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Set-up the new master (is skipped in our case because a slave becomes master).&lt;/li&gt;&lt;li&gt;Do a consistent backup of the master (which takes time and, depending on the used storage engines, blocks writing).&lt;/li&gt;&lt;li&gt;Set-up all slaves one by one and point them to the new master (takes also time).&lt;/li&gt;&lt;/ol&gt;During these steps your production environment provides partially limited resources.&lt;br /&gt;To avoid or at least reduce this problem we are looking for an abbreviation of the whole process:&lt;br /&gt;&lt;br /&gt;Step 1: is obsolete in our scenario.&lt;br /&gt;Step 2: Can be circumvented when we use a storage engine which allows us to make consistent backups (for example InnoDB) or when we use a very fast backup method (for example LVM snapshots).&lt;br /&gt;Step 3: We can re-use all the slaves which have the same or older information than the new elected master. Slaves which have newer informations or in some other exceptional cases (see below) have to be set-up anyway as recommended.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;How to do this?&lt;/span&gt;&lt;br /&gt;IMHO the best is to show that in a little demo. For this I have set-up a environment like in scenario 1) and/or 2). There I have created my favourite table test as follows:&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;CREATE TABLE test (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  `id` int(11) NOT NULL AUTO_INCREMENT,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  `data` varchar(32) DEFAULT NULL,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  `ts` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;  PRIMARY KEY (`id`));&lt;/span&gt;&lt;/blockquote&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;/blockquote&gt;As next step we simulate the application as follows:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;br /&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;br /&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;/blockquote&gt;To simulate a lag on one or more of the slaves we stop the replication on these:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;STOP SLAVE;&lt;br /&gt;&lt;/blockquote&gt;Then we do some more application action on the master:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;br /&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;/blockquote&gt;And then we crash the master!&lt;br /&gt;From this point on we have the situation which could happen in the real world: Master is crashed and different slaves (can) have different positions relatively to the master:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Find the most actual slave&lt;/span&gt;&lt;br /&gt;To find the slave which is the most actual one you have to gather some information on the slaves. This can be done as follows:&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;mysql&gt; PAGER grep Master_Log;&lt;br /&gt;mysql&gt; SHOW SLAVE STATUS\G&lt;br /&gt;mysql&gt; PAGER ;&lt;br /&gt;&lt;/blockquote&gt;You also have to do this step in scenario b) because we want to know which slave can be taken and which one has to be set-up from scratch.&lt;br /&gt;Then we get some output for example like this:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;Slave 1:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;             Master_Log_File: bin-3311.000006&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          Read_Master_Log_Pos: 929&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Relay_Master_Log_File: bin-3311.000006&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          Exec_Master_Log_Pos: 929&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;Slave 2:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;              Master_Log_File: bin-3311.000006&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          Read_Master_Log_Pos: 635&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;        Relay_Master_Log_File: bin-3311.000006&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;          Exec_Master_Log_Pos: 635&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;What we have to assure first is, that all the slave have caught up with writing the data from the relay log to slave. This is assured by comparing Master_Log_file/Read_Master_Log_Pos with Relay_Master_Log_file/Exec_Master_Log_Pos. If these values are the same then the slave has caught-up. Otherwise wait until they become the same.&lt;br /&gt;When this is done we have to find, which slave is the most recent one. This is simple: Higher value is equal to newer information (also consider the log file not only the position!).&lt;br /&gt;In scenario a) the one (or one of these) is elected as new master.&lt;br /&gt;In our scenario this is Slave 1!&lt;br /&gt;&lt;br /&gt;In scenario 2 all slaves which are newer than the pre-elected new master must be rebuild from the new master.&lt;br /&gt;Slave 1 is newer than slave 2. If slave 2 was pre-elected as new master slave one must be rebuild from the new master.&lt;br /&gt;From all the slaves which have a different position than the new master calculate the delta to the new master:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;Calculate delta: 6.929 - 6.635 = 294&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;When the log file is different we cannot use these informations and we have to rebuild this slave from the new master.&lt;br /&gt;Now we have defined, which one will become the new master and which slaves are in line, which are ahead and which are behind the new master.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:130%;"&gt;Set-up the new environment&lt;/span&gt;&lt;br /&gt;To avoid any troubles we to a STOP SLAVE on all slaves first.&lt;br /&gt;Then we do a RESET SLAVE on the new master.&lt;br /&gt;Now for every slave which is not rebuild from the master we have to calculate the position where to start the replication from. To do this we have to gather the actual position of the new master:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;SHOW MASTER STATUS;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;+-----------------+----------+--------------+------------------+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB |&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;+-----------------+----------+--------------+------------------+&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;| bin-3312.000002 |     2857 |              |                  |&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;+-----------------+----------+--------------+------------------+&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;And for every slave we can calculate the delta:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;==&gt; 2857 - 294 = 2563&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;When the value becomes negative this means that we have to start in an older log-file than the actual one. I did not find any rule to calculate the exact position in this case. So unfortunately we also have to set-up these slaves from the backup.&lt;br /&gt;&lt;br /&gt;As soon as we have these values calculated we can start the application running against the new master and we can also start now with the new consistent backup for all the slaves we have to set-up again from the backup.&lt;br /&gt;&lt;blockquote style="font-family: courier new;"&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;br /&gt;INSERT INTO TEST VALUES (NULL, 'Insert on Master', NULL);&lt;/blockquote&gt;On the slaves which are OK for aligning with the new master we have to change the master and the new positions now:&lt;br /&gt;&lt;blockquote&gt;&lt;span style="font-family:courier new;"&gt;CHANGE MASTER TO master_host='laptop', MASTER_USER='replication', MASTER_PORT=3312, MASTER_PASSWORD='replication';&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;CHANGE MASTER TO MASTER_LOG_FILE='bin-3312.000002', master_log_pos=2563;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;START SLAVE;&lt;/span&gt;&lt;br /&gt;&lt;/blockquote&gt;That's it!&lt;br /&gt;If you would like to here more about such stuff please let me know. We are glad to help you with some consulting...&lt;br /&gt;I have also most of this stuff in some scripts so this could be easily automated...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-5394715872579152552?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/5394715872579152552/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=5394715872579152552' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5394715872579152552'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/5394715872579152552'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/09/activeactive-fail-over-cluster-with.html' title='Active/active fail over cluster with MySQL Replication'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-8605331434819034855</id><published>2008-08-25T19:07:00.005+02:00</published><updated>2008-08-25T19:17:23.742+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='mysql maintenance jobs'/><title type='text'>Typical automated MySQL maintenance jobs</title><content type='html'>&lt;style type="text/css"&gt;!--   @page { margin: 2cm }   P { margin-bottom: 0.21cm }   H3 { margin-bottom: 0.21cm }   H3.western { font-family: "Nimbus Sans L", sans-serif }   H3.cjk { font-family: "DejaVu Sans" }   H3.ctl { font-family: "DejaVu Sans" }   TD P { margin-bottom: 0cm }   TD P.western { font-size: 10pt }   CODE { font-family: "Cumberland AMT", monospace }  --&gt;  &lt;/style&gt;  &lt;p class="western"&gt;The following maintenance jobs are typically run against a MySQL database:&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;p class="western"&gt;“Backup”&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;Clean-up binary logs.&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;Optimize tables&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;Purge query cache&lt;/p&gt;  &lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;Rotate binary logs&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt; &lt;h3 class="western"&gt;Backup&lt;/h3&gt; &lt;p style="text-align: justify;" class="western"&gt;A backup is not a typical maintenance job. But it behaves more or less like one. The backup should be done regularly depending on the restore/PITR (Point in Time Recovery) requirements.&lt;/p&gt; &lt;p style="text-align: justify;" class="western"&gt;Make sure, that in the backup all the necessary files (data files, transaction log files, configuration files and binary log files) are included. To prove that the backup process is working properly a regular restore should be performed. This can ideally be combined with the set-up of new database instances for developers or testing.&lt;br /&gt;&lt;/p&gt; &lt;h3 class="western"&gt;Clean-up the binary logs&lt;/h3&gt; &lt;p class="western"&gt;The binary logs can be cleaned-up in two ways:&lt;/p&gt; &lt;p class="western"&gt;a) Passive by MySQL itself:&lt;/p&gt; &lt;table border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="100%"&gt;  &lt;col width="256*"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td bgcolor="#ffffcc" valign="top" width="100%"&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;b&gt;&lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;#    my.cnf&lt;/span&gt;&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;        &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;b&gt;&lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;expire_logs_days    = 7&lt;/span&gt;&lt;/code&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;p class="western"&gt;b) Active by the customers environment:&lt;/p&gt; &lt;table border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="100%"&gt;  &lt;col width="256*"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td bgcolor="#ffffcc" valign="top" width="100%"&gt;&lt;div&gt;        &lt;/div&gt;&lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm; font-weight: bold; text-align: justify;"&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;mysql&gt;    PURGE MASTER LOGS TO 'binarylog.000999';&lt;/span&gt;&lt;/code&gt;&lt;/span&gt;&lt;/p&gt;            &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm; font-weight: bold;"&gt;    &lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;mysql&gt; &lt;/span&gt;&lt;/code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;PURGE    MASTER LOGS BEFORE '2008-07-29 22:46:26';&lt;/span&gt;&lt;/p&gt;&lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;&lt;br /&gt;   &lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;p style="text-align: justify;" class="western"&gt;Make sure NO binary logs are purged which are still needed by a slave. In this situation the slave is lost and has to be set-up from scratch.&lt;/p&gt; &lt;p style="text-align: justify;" class="western"&gt;Make also sure binary logs are not removed by a file system operation (rm bin-log.*). Otherwise the database gets confused.&lt;/p&gt; &lt;h3 class="western"&gt;Optimize table&lt;/h3&gt;  &lt;div style="text-align: justify;"&gt;After large UPDATE or INSERT/DELETE operations or long time tables are blown up and contain a lot of unused space. This unused space can be partially reclaimed by optimizing the table again.&lt;br /&gt;&lt;/div&gt;&lt;p class="western"&gt;&lt;br /&gt;&lt;/p&gt; &lt;table border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="100%"&gt;  &lt;col width="256*"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td bgcolor="#ffffcc" valign="top" width="100%"&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;b&gt;mysql&gt; OPTIMIZE    TABLE &lt;table_name&gt;;&lt;/table_name&gt;&lt;/b&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;p style="text-align: justify;" class="western"&gt;This operation internally copies the whole table and therefore can take a long time!&lt;/p&gt; &lt;h3 class="western"&gt;Purge query cache&lt;/h3&gt;  &lt;p style="text-align: justify;" class="western"&gt;When there are SELECT queries with different sizes of result sets the query cache gets de-fragmented. This is shown by a lot of free space in the query cache but also a lot of not cached queries. Here it makes sense to purge the query cache from time to time.&lt;br /&gt;&lt;/p&gt; &lt;table border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="100%"&gt;  &lt;col width="256*"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td bgcolor="#ffffcc" valign="top" width="100%"&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;b&gt;mysql&gt; FLUSH    QUERY CACHE;&lt;/b&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;h3 class="western"&gt;Binlog rotate&lt;/h3&gt;  &lt;div style="text-align: justify;"&gt;Binary logs can only be rotated by size. Sometimes you want to have them rotated by time. You can do this as follows (for example with a cron job):&lt;br /&gt;&lt;/div&gt;&lt;p class="western"&gt;&lt;br /&gt;&lt;/p&gt; &lt;table border="1" bordercolor="#000000" cellpadding="4" cellspacing="0" width="100%"&gt;  &lt;col width="256*"&gt;  &lt;tbody&gt;&lt;tr&gt;   &lt;td bgcolor="#ffffcc" valign="top" width="100%"&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;code&gt;&lt;span style="font-family:Nimbus Mono L,monospace;"&gt;&lt;b&gt;mysql&gt; FLUSH    LOGS;&lt;/b&gt;&lt;/span&gt;&lt;/code&gt;&lt;/p&gt;    &lt;p class="western" style="margin-right: 0.5cm; text-indent: 0.5cm;"&gt;    &lt;br /&gt;   &lt;/p&gt;   &lt;/td&gt;  &lt;/tr&gt; &lt;/tbody&gt;&lt;/table&gt;  &lt;p class="western" style="margin-bottom: 0cm;"&gt;What other MySQL maintenance jobs are you performing (not application related) I am very interested in...&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-8605331434819034855?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/8605331434819034855/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=8605331434819034855' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/8605331434819034855'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/8605331434819034855'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/08/typical-automated-mysql-maintenance.html' title='Typical automated MySQL maintenance jobs'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-2493871353963611911</id><published>2008-06-28T12:00:00.004+02:00</published><updated>2008-06-28T12:10:23.942+02:00</updated><title type='text'>My thoughts about MySQL (Cluster) replication</title><content type='html'>&lt;style type="text/css"&gt;--   @page { size: 8.27in 11.69in; margin: 0.79in }   P { margin-bottom: 0.08in }   P.western { font-size: 10pt }  --&gt;  &lt;/style&gt;  &lt;p class="western"&gt;According to Johans wishes I write down my concerns about MySQL (Cluster) replication. These items are things I run again and again into it with customers:&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/p&gt; &lt;ul&gt;&lt;li&gt;&lt;span style="font-weight: bold;"&gt;SQL-nodes are still loosing too easy connection to cluster&lt;/span&gt; after data node or management node restart (which leads into gaps, see next point). Automatic fail over or reconnection is just a dream (maybe it works in about 90% of the cases at least)..&lt;br /&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Gaps&lt;/span&gt;: Whenever I do a cluster reconfiguration  (should not be necessary too often, see loosing connection above) or  a mysqld restart I get a gap (these are the planned ones, see also  automatic channel fail over). Then we have the not planned ones...&lt;br /&gt;I  cannot understand, why we are not able to keep at least a certain  amount of traffic in a binlog-injector-buffer to avoid the majority  of these gaps. This could be something like a Round-Robin buffer  which stores all the cluster information which should be sent to the  binlog-injector thread. When we configure this buffer to 1 Gbyte we  can keep close to 2 minutes of traffic (10 Mbyte/s traffic) which  should be fine to cover just hiccups and quick restarts of mysql. In  other environments where we have much less traffic we can store  there even hours of traffic which really should make look us  unbreakable.&lt;br /&gt;Together with an automatic channel fail over this  should be much more robust.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Automatic channel fail over&lt;/span&gt;: It should not be  too difficult to automatically switch from one channel to an other  (or a third) one. If the issues above are solved, it is also less  likely, that a channel fail over is necessary.&lt;br /&gt;A gap event should  trigger a channel fail over and a STOP SQL THREAD command and not  just stopping the replication with an error. It should also be  possible to make an automatic switch back to the original slave  again if this slave is still talking to its master after the gap to  see if it possibly could continue working...&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Atomic operations&lt;/span&gt;: They do not have to be  necessarily durable but atomic. This problem we have on the master  side (as described in the issue 27201) and also on the slave side.  When we guarantee atomicity we should not loose to much in  performance (don't we?) but can avoid a lot of troubles in  replication: The relay-log is not atomic with the slave at all. If I  crash a slave under heavy load it will stick in troubles (in about  25% of the cases). This is reproducible and a bug is filed for this.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Binary-log mechanism is a nightmare for every  DB operator&lt;/span&gt;: Making errors in MySQL replication and restore/recovery  is very easy (including Cluster PITR). We should make the  mysql-restore-recovery mechanism aware of the last applied  transaction (global trx id?) and by default it should deny to apply  binary-logs with the wrong file or position (at some other databases  you cannot even force it to do it wrong!).&lt;br /&gt;The Cluster  Recovery/PITR is further not documented and also should follow this  rules/mechanism. It would also be nice if, after ndb_restore -m -r  -e is done it would ask for the binary log to apply next (at the  right position!).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Rolling restart&lt;/span&gt;: From time to time it  happens, that a rolling restart is necessary. This has to be done  manually for each node (some customers were writing scripts for  this) but even worse you also have to switch the tool to do this.&lt;br /&gt;My  suggestion is: a) Implement a ROLLING RESTART command and b) also  allow to restart SQL-Nodes from the mgmd (mgmd and mysqld are  talking to each other anyway (see binlog injector thread), so it  should not be too difficult to send a SIGHUP from the mgmd to the  mysqld).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;&lt;span style="font-weight: bold;"&gt;Monitoring&lt;/span&gt;: MySQL Cluster Monitoring without  the MGMD-API is a nightmare too. And also with the MGMD-API it is so  poor! What I would like to have is a standardized interface to my  system metrics (namely SQL!). And then all the important information  (performance metrics, buffer fill degree, etc.) in some cluster  tables. Basically all the the stuff which is written to the cluster  log with ALL REPORT MemoryUsage, ALL REPORT BackupStatus and ALL  CLUSTERLOG STATISTICS=15 (or maybe ALL events?)). So I can access  them easily.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p class="western"&gt;Just a little (maybe?) bug I run into it with  recent MySQL Cluster releases: A Gap requires now more than one (at  least 2) set global sql_slave_skip_counter=1 statements to make  slave running again... This makes the replication less predictable  for automatising processes.&lt;/p&gt; &lt;/li&gt;&lt;/ul&gt;  &lt;p class="western"&gt;All these points endanger my operative production life and can cause errors in enterprise and carrier grade environments.&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-2493871353963611911?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/2493871353963611911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=2493871353963611911' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2493871353963611911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/2493871353963611911'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/06/my-thoughts-about-mysql-cluster.html' title='My thoughts about MySQL (Cluster) replication'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-4586991464149252149</id><published>2008-05-29T13:43:00.002+02:00</published><updated>2008-05-29T13:53:51.267+02:00</updated><title type='text'>Some more details about DiskSyncSize</title><content type='html'>The parameter &lt;span style="font-weight: bold;"&gt;DiskSyncSize&lt;/span&gt; is a MySQL Cluster parameter and was added in MySQL 5.1.23.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;After the amount of &lt;disksyncsize&gt; stored bytes of data per file, the data node will fsync (flush) the LCP file to disk, even if a fsync is not needed for consistency.&lt;br /&gt;This is done because the OS will otherwise buffer all the writes, and when a fsync is really needed, it can take a lot of time...&lt;br /&gt;&lt;br /&gt;Originally this parameter was hard coded. Now it defaults to 4 Mbyte.&lt;br /&gt;&lt;br /&gt;The parameter DiskSyncSize is related to the parameters NoOfDiskPagesToDiskAfterRestartTUP and NoOfDiskPagesToDiskAfterRestartACC which are deprecated right now. It does NOT replace the parameter &lt;span style="font-weight: bold;"&gt;TimeBetweenLocalCheckpoint&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;This parameter should not be changed on any OS (with reasonable settings). With &lt;span style="font-weight: bold;"&gt;ODIRECT&lt;/span&gt; it is not used at all.&lt;br /&gt;&lt;br /&gt;Thanks to Jonas for the help.&lt;br /&gt;&lt;/disksyncsize&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-4586991464149252149?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/4586991464149252149/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=4586991464149252149' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/4586991464149252149'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/4586991464149252149'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/05/some-more-details-about-disksyncsize.html' title='Some more details about DiskSyncSize'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-6864099895737809960.post-6069234750120492237</id><published>2008-05-18T16:44:00.002+02:00</published><updated>2008-05-18T16:51:58.067+02:00</updated><title type='text'>With MySQL-Enterprise Montior through firewalls</title><content type='html'>Sometimes it is nice to show customers the functionality of MySQL-Enterprise Monitor (aka Merlin). I install the agents on the servers and the dashboard runs on my laptop. But very often only ssh is open to these servers.&lt;br /&gt;So how to dig a whole through the firewall for MySQL-Enterprise Monitor?&lt;br /&gt;&lt;blockquote&gt;laptop&gt; ssh -R 18080:&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;localhost&lt;/span&gt;:18080 oli@where_the_agent_sits&lt;/blockquote&gt;Maybe trivial for you but for me its hard to remember...&lt;br /&gt;&lt;blockquote&gt;&lt;/blockquote&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-6069234750120492237?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/6069234750120492237/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=6069234750120492237' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6069234750120492237'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/6069234750120492237'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/05/with-mysql-enterprise-montior-through.html' title='With MySQL-Enterprise Montior through firewalls'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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-6864099895737809960.post-3287844417740298084</id><published>2008-04-09T08:44:00.004+02:00</published><updated>2008-04-09T08:50:05.599+02:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='blog'/><category scheme='http://www.blogger.com/atom/ns#' term='mysql'/><category scheme='http://www.blogger.com/atom/ns#' term='move'/><title type='text'>Move my blog</title><content type='html'>To look a little bit more nice and because I do not want to spend to much time into my own blog/feed software I have decided to move all my writings here.&lt;br /&gt;&lt;br /&gt;But the most interesting for me to is the readers feed back...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/6864099895737809960-3287844417740298084?l=shinguz.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://shinguz.blogspot.com/feeds/3287844417740298084/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=6864099895737809960&amp;postID=3287844417740298084' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3287844417740298084'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/6864099895737809960/posts/default/3287844417740298084'/><link rel='alternate' type='text/html' href='http://shinguz.blogspot.com/2008/04/move-my-blog.html' title='Move my blog'/><author><name>Shinguz</name><uri>http://www.blogger.com/profile/11195863756524022642</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>
