MySQL Logging – Can Queries Write to Binary Log Before Execution Completes?

logMySQLmysql-5.5

I have a Database which is a Slave and a Master. e.g. it replicates data from our main site, and then onwards to a set of slave databases. (this is mainly a test facility so not monitored out of hours).

On Sunday morning at 7:55 it started executing an INSERT query. This is a standard query that executes thousands of times a day. Its a single query, not part of a transaction. There are no triggers on that table. This table (and all others) are INNODB.

But, on this occasion it got stuck. When I came in the office today it had been running for 24 hours (apparently). And replication was a day behind.

However, when I looked in the Binary logs it showed as COMMITed.

#160814  7:55:25 server id 21  end_log_pos 103319397    Query   thread_id=635785334 exec_time=4294967294    error_code=0
SET TIMESTAMP=1471157725/*!*/;
INSERT INTO tablename . . . 
/*!*/;
# at 103319397
#160814  7:55:25 server id 21  end_log_pos 103319424    Xid = 284047583
COMMIT/*!*/;
# at 103319424

I checked the Slave databases, and it was on present on there as you'd expect.

I have a monitoring system which records (amongst other things) the processlist, and it shows that for that INSERT query it was perpetually stuck at STATE = UPDATE.

I also checked the slow query log to see if it was in there, and it wasn't.

My understanding was that a query couldn't be written to the binary log until it was commmited on the master, so can anyone explain what has happenned here?

There was a knock on affect in that once out test system tried to connect at 8:38 this morning, the first SELECT query also got stuck, and then it refused all connetions. So I was forced to restart the database.
At which point it ran crash recovery, and carried on as if nothing had happenned.

It is MySQL 5.5.47 and using Statement Based Replication.

Best Answer

If you're getting conflicting info from different sources, use the official documentation:

http://dev.mysql.com/doc/refman/5.5/en/binary-log.html

Binary logging is done immediately after a statement or transaction completes but before any locks are released or any commit is done. This ensures that the log is logged in commit order.

This means there is a narrow window in which a failure could cause an uncommitted transaction to exist in the binary log but not in the database. This seems to be what has happened in your case.

For example, if you are using InnoDB tables and the MySQL server processes a COMMIT statement, it writes the whole transaction to the binary log and then commits this transaction into InnoDB. If the server crashes between those two operations, the transaction is rolled back by InnoDB at restart but still exists in the binary log. To resolve this, you should set --innodb_support_xa to 1. Although this option is related to the support of XA transactions in InnoDB, it also ensures that the binary log and InnoDB data files are synchronized.