The perils of InnoDB with Debian and startup scripts

January 28, 2009
Author
Baron Schwartz
Share this Post:

Are you running MySQL on Debian or Ubuntu with InnoDB? You might want to disable /etc/mysql/debian-start. When you run /etc/init.d/mysql start it runs this script, which runs mysqlcheck, which can destroy performance.

It can happen on a server with MyISAM tables, if there are enough tables, but it is far worse on InnoDB. There are a few reasons why this happens — access to open an InnoDB table is serialized by a mutex, for one thing, and the mysqlcheck script opens all tables. One at a time.

It’s pretty easy to get into a “perfect storm” scenario. For example, I’m working with one client right now who has a hosted multi-tenanting application that keeps each customer in its own database. So they have a lot of databases and a lot of tables. And they’re running on Amazon EC2 with 8G of RAM and EBS storage, which is slower than typical directly-attached server-grade RAID storage. Since they have a lot of tables, InnoDB uses over 3.5G of memory for its data dictionary (the subject for another post — we’re working on a fix) and so we can’t make the buffer pool as large as we’d like to.

To avoid physical I/O all the time we need to get some reasonable amount of data into the buffer pool. But we have to do this without death-by-swapping, which would be extremely slow on this machine, so we need to stop the buffer pool and the OS cache from competing. My chosen strategy for this was to set innodb_flush_method=O_DIRECT. We could also tune the OS, but in my experience that’s not as effective when you’re really pushing to get memory into the buffer pool. Remember we have 3.5G of memory less to play with, solely due to the data dictionary.

But this strategy will only reduce physical reads if the buffer pool follows a typical access pattern. That is, some of the data is in your working set and will stay in the buffer pool, some small part of it will move in and out of the buffer pool, and some won’t be needed.

And that’s where the Debian startup script breaks down entirely, because it doesn’t follow this pattern. It’s going to open every table, regardless of whether user queries require it or not. On big servers I’ve seen it literally run for days (or longer). In the meanwhile, it’ll interfere with everything else going on. Look what happens:

Notice all those processes in ‘statistics’ status. Why is that happening? Look at SHOW INNODB STATUS:

Everyone is waiting for mutexes, and they are all waiting for thread 1158064464 which has reserved it. If you hunt through the TRANSACTIONS section, you can see the OS thread IDs, and that one is the debian-sys-maint thread. You also see the other threads:

And correlating the thread ID back to the semaphores, you see thread 1159956816 is waiting for the semaphore.

Notice that this is effectively a global lock. The debian-sys-maint thread is not touching the same tables as the other queries; it’s just touching the same internal structures. So a user working on table A can interfere with a user that wants access to table B.

The real solution is to disable this startup process. It’s not even needed for InnoDB. Sooner or later you’ll find yourself fighting with it. You can just put “exit 0;” at the top.

The solution I chose in this case?

Immediately afterward everything cleared up.

Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Far
Enough.

Said no pioneer ever.
MySQL, PostgreSQL, InnoDB, MariaDB, MongoDB and Kubernetes are trademarks for their respective owners.
© 2026 Percona All Rights Reserved