Wednesday, August 29, 2012

MySQL Cluster: Troubleshooting Error 157 / 4009 Cluster Failure


Suddenly your application starts throwing "error 157" and performance degrades or is non-existing. It is easy to panic then and try all sorts of actions to get past the problem. We have seen several users doing:
  • rolling restart
  • stop cluster / start cluster
because they also see this in the error logs:
120828 13:15:11 [Warning] NDB: Could not acquire global schema lock (4009)Cluster Failure

That is not a really a nice error message. To begin with, it is a WARNING when something is obviously wrong. IMHO, it should be CRITICAL. Secondly, the message ‘Cluster Failure’ is misleading.  The cluster may not really have failed, so there is no point trying to restart it before we know more.

So what does error 157 mean and what can we do about it?

By using perror we can get a hint what it means:

$ perror 157
MySQL error code 157: Could not connect to storage engine

What this means is simply as it says, one SQL node is not connected to the NDB storage engine.  It can be that you have messed up the ndb-connectstring in the my.cnf of that SQL node.
It is often the case that someone has been doing ALTER TABLEs, and for some reason, the schema files have been corrupted or is of the wrong version on one or more SQL nodes. It would make sense to check the SQL nodes for potential problems there.

If you have multiple SQL nodes, you probably have the SQL nodes behind a load balancer. Which MySQL is really causing this problem? One of them, or all of them?
Let’s take a look from one of the SQL nodes:

mysql> show global status like 'ndb_number_of%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Ndb_number_of_data_nodes       | 2     |
| Ndb_number_of_ready_data_nodes | 2     |
+--------------------------------+-------+
2 rows in set (0.00 sec)

This is perfect, we have two Data nodes , and two of them are ready. This means that this particular SQL node is connected to the NDB storage engine. Now, let's look at another one:

mysql> show global status like 'ndb_number_of%';
+--------------------------------+-------+
| Variable_name                  | Value |
+--------------------------------+-------+
| Ndb_number_of_data_nodes       | 0     |
| Ndb_number_of_ready_data_nodes | 0     |
+--------------------------------+-------+
2 rows in set (0.00 sec)

This does not look good, this SQL node is not connected to the Data nodes. Now iterate over the remaining 62 MySQL servers or how many you have to find the bad apples. However, I prefer myself to spot the faulty ones like this:

Screenshot from Severalnines ClusterControl

Now, we can stop the SQL nodes that are marked as "red":
1.     Stop the MySQL server:
service mysql stop
2.    Go into the database(s) you have in the datadir of the MySQL server:
cd /var/lib/mysql/mydatabase/
3.    Remove .frm files and .ndb files:
for x in `ls *.ndb`; do rm `basename $x .ndb`.frm; rm `basename $x`;  done
4.    Start the MySQL server
service mysql start
Is step 2) safe to do? 
Yes, the .frm files of the NDB tables are stored in the data dictionary inside the data nodes. By removing these files, and restarting the MySQL server, the MySQL server will fetch the missing .frm files from the data nodes, and you will end up with fresh ones.

Hope this helps someone,
Johan





Friday, May 11, 2012

MySQL Cluster: mysqld Sort aborted and error 4006


Just a note on a problem that some people may find useful and may work for you if you have the same issue.

A client had a problem this morning with queries being aborted with the error message:

 Got temporary error 4006 'Connect failure - out of connection objects (increase MaxNoOfConcurrentTransactions)' from NDBCLUSTER

Here you would think that increasing the number of MaxNoOfConcurrentTransactions would help, but the root cause is something else (the client is not even close of hitting the default MaxNoOfConcurrentTransactions)

It turned out that during the night a couple of updates to the schema had been made (ALTER TABLEs to convert a couple of TEXT to  VARCHAR, so that a particular index could be created).

Looking in the mysql error logs we had:

120511 10:47:05 [ERROR] /usr/local/mysql/bin/mysqld: Sort aborted: Got temporary error 4006 'Connect failure - out of connection objects (increase MaxNoOfConcurrentTransactions)' from NDBCLUSTER
120511 10:47:27 [ERROR] Got error 4006 when reading table './database_name/table_name'

I suspected there was something wrong (corrupted?) with the .frm files that the mysql server is caching in the datadir, and simply did, for all mysql servers:

  • stop mysqld
  • remove all .frm for all ndb tables in the database
  • start mysqld
  • and finally a "SHOW TABLES" to get all the .frm files back up from the data nodes into the local datadir of the mysqld
Now, the problem is gone, but I can't explain how reading a table can cause error 4006...

Hope this helps someone.