Faking a slave: Subscribing to mysql row-based-replication changes

In complex systems it’s often useful to be able to receive notification when rows have been modified in MySQL so that you can invalidate various external caches or indexes. For example: memcached, Sphinx, Lucene.

In the case of MySQL’s default statement-based replication this can be quite tricky to do, as it would likely require an SQL parser to determine what was intended to be modified. However, this is made much simpler with Row-based Replication (something I recommend switching to).

A C++ library exists to be able to listen to MySQL replication, but what I want to demonstrate is that it is also very simple to be able to do this with mysqlbinlog:


shell> mysqlbinlog --read-from-remote-server --stop-never --host localhost.localdomain --port 5616 -u msandbox -pmsandbox --verbose mysql_sandbox5616-bin.000004 | grep '^### '

To explain how this command works:

  • --read-from-remote-server tells mysqlbinlog to act like a slave, and fetch remote files rather than local (new option to 5.6).
  • --stop-never makes mysqlbinlog block waiting for a continual stream of updates, rather than exiting. Perfect!
  • --verbose rewrites row-based replication events to be pseudo SQL statements. The pseudo statements are very easy to parse. For example:
    ### DELETE FROM `test2`.`a`
    ### WHERE
    ###   @1=1
    ### INSERT INTO `test2`.`a`
    ### SET
    ###   @1=1
    ### UPDATE `test2`.`a`
    ### WHERE
    ###   @1=10
    ### SET
    ###   @1=20
    

    Noting that a multi-row statement will appear as individual statements via --verbose. Row-based events also default to sending all columns in the row, not just those that are changed.

  • The grep '^### ' statement is just a lazy way of stripping out everything except pseudo SQL statements.

Advanced Usage

You can fairly easily extend the above to track your progress reading through the master’s binary logs. This will make it easier to resume from where you left off if there is a crash. Just remove the grep, and keep track of:

  • Positional markers just before DML events. These are marked in bold here:
    # at 191
    #140526 15:28:27 server id 10  end_log_pos 239 CRC32 0x559a84a8     GTID [commit=yes]
    SET @@SESSION.GTID_NEXT= '9f0ce61c-bb92-11e3-89fd-f056da47d247:17'/*!*/;
    # at 239
    #140526 15:28:27 server id 10  end_log_pos 312 CRC32 0xff074c19     Query   thread_id=1 exec_time=0 error_code=0
    SET TIMESTAMP=1401143307/*!*/;
    BEGIN
    /*!*/;
    # at 312
    #140526 15:28:27 server id 10  end_log_pos 357 CRC32 0x74b1ad7f     Table_map: `test2`.`a` mapped to number 71
    # at 357
    #140526 15:28:27 server id 10  end_log_pos 397 CRC32 0x2c6f8b8d     Write_rows: table id 71 flags: STMT_END_F
    
    BINLOG '
    C8CDUxMKAAAALQAAAGUBAAAAAEcAAAAAAAEABXRlc3QyAAFhAAEDAAF/rbF0
    C8CDUx4KAAAAKAAAAI0BAAAAAEcAAAAAAAEAAgAB//4KAAAAjYtvLA==
    '/*!*/;
    ### INSERT INTO `test2`.`a`
    ### SET
    ###   @1=10
    
  • Events that show that the binary log file itself is being rotated. For example, the result of FLUSH LOGS is:
    # at 4
    #691231 16:00:00 server id 10  end_log_pos 0 CRC32 0x7800af55   Rotate to mysql_sandbox5616-bin.000006  pos: 4
    

Conclusion

This might not be as robust in all cases as using the C++ API, but it sure beats the alternative. Gone are my days of writing complex sets of triggers to write to an “events” table, which I poll continually from an external script.

MySQL soon to store system tables in InnoDB

In the MySQL team, we are changing the system tables currently located in the mysql schema from MyISAM to InnoDB.

Looking at this historically:

  • MyISAM was the default storage engine up until MySQL 5.5.
  • In 5.5 almost 4 years ago, the default storage engine changed to InnoDB, however system tables used for features such as storing privileges and timezones remained as MyISAM.

Unlike MyISAM, InnoDB is an ACID compliant storage engine, with the behaviour that once a transaction commits, modifications are able to survive power-loss or other failures. This is a solid foundation to build applications on, since developers will need to handle fewer failures. To use an example:

  1. Customer places an order
  2. A confirmation email is sent
  3. Power is lost

Without durability, (2) could occur with no record of (1) occurring! Durability is a great feature. However, we do not currently offer this for the system tables which use MyISAM. To use an example:

  1. A DBA revokes a user’s privilege to MySQL (the command returns success)
  2. Power loss occurs
  3. Upon restore, the revoke never applied.

By switching to InnoDB we are improving the experience of system-related tasks by ensuring durability that ACID provides.

This change will have the effect that InnoDB will be required for all MySQL installations, and the configuration setting --skip-innodb will no longer make sense. Users will still be able to use the MyISAM storage engine, and MyISAM-heavy installations can continue to configure the InnoDB buffer pool to as low as 5MB – taking up very little memory.

This is a great step forward for MySQL, and I am personally very excited to see this change. Many in the MySQL community have been requesting this change for years, and we’re happy to now be working on it. If you have any thoughts, please leave a comment, or email me!

Proposal to deprecate COM_REFRESH packet

In the MySQL team we are proposing to deprecate the COM_REFRESH packet in favor of specific queries to execute FLUSH commands. To provide a bit of context:

  • The MySQL server protocol allows for clients to speak API commands via both a query and binary protocol interface. The set of the API commands can be seen in the MySQL Client/Server Protocol internals documentation, or very simply as they appear in a single switch statement:
    # ./sql/sql_parse.cc:1009 (simplified view)
    
      switch (command) {
    
      case COM_REGISTER_SLAVE:
      {
        /* do stuff */
        break;
      }
      case COM_QUERY:
      {
        /* parse query, do stuff */
        break;
      }
      case COM_REFRESH:
      {
       /* equivalent to running a FLUSH command */
        break;
      }
      case COM_SHUTDOWN:
      {
        kill_mysql();
        break;
      }
    }
    
  • The historical advantage of having a binary protocol meant that less bytes needed to be transfered across the network as well as less processing on the server, since parsing of statements is not required.
  • The disadvantage of the binary protocol is that it is less extensible. In the case of COM_REFRESH it was designed to accept only a 1 byte payload to indicate which flush command to run. A quick look at the MySQL manual shows that there are now more than eight (1 byte payload = 8 possible flags) flush commands available. This leads to API inconsistency as some commands are available via the binary interface and others are not.

Our proposed solution to this problem is to deprecate the binary interface for refresh commands and promote usage of the query interface (FLUSH LOGS, FLUSH TABLES, FLUSH HOSTS etc) instead. While we have no immediate plans to remove the COM_REFRESH binary interface (and thus break older clients) we are seeking feedback on the direction of this change. Please leave a comment, or get in touch!

Proposal to deprecate the old password format

Improving security has been a high priority for MySQL 5.7. To give you an idea of some of the changes to date, I recommend reading Todd Farmer’s blog: Redefining –ssl option, Password expiration policy, AES256 encryption.

In MySQL 5.7, we are also proposing to remove the ‘old’ format for saving passwords. To provide some historical context:

  • The old password format is a 16-byte hash and considered to be cryptographically weak. Code appears online (I won’t link to it) which allows the hash to be brute-forced in a small-enough amount of time.
  • Ten years ago (2004), MySQL 4.1 introduced a stronger password hash format based on SHA1. The old password hash continued to be supported, since client libraries connecting to MySQL needed time to upgrade to support the new authentication scheme. A configuration setting of secure-auth=1 allowed a DBA to enforce that users could only authenticate using new password hashes, but it was not enabled by default. Another configuration setting (old-passwords=1) allowed passwords to still be generated in the weak format.
  • MySQL 5.6 (2013) enabled secure-auth=1 by default, preventing users from connecting to the server using old password hashes. However, it still permits a DBA to configure secure-auth=0 + old-passwords=1 allowing weak hashes to be generated and used. As an aside, 5.6 also introduced a new SHA256 password hash option.

This brings us to today’s discussion. We would like to propose that:

  • Setting secure-auth=0 + old-passwords=1 is officially deprecated as of MySQL 5.6. The MySQL manual pages will be updated to discourage against these settings, and warnings will be written to the server error log on startup when they are in use.
  • In a future version, support for setting secure-auth=0 + old-passwords=1 will be removed. Since our policy is to support each GA release for 8 years this means that using old-password hashing will already be supported via MySQL 5.6 until 2021. Extending support beyond this leaves us in a less secure position.

    We are proposing for removal in MySQL 5.7, but are open to suggestions as to what is an acceptable timeframe.

We value your feedback regarding this proposal:

  • Are you currently using secure-auth=0 or old-passwords=1?
  • Do you use a legacy connector that will not support the new (4.1+) authentication?
  • If you do not agree with removal in MySQL 5.7, which version would you consider more suitable?

Please leave a comment, or get in touch!

Calling for all mysql_install_db feature requests

mysql_install_db is the program that is responsible for bootstrapping a fresh copy of MySQL and making sure all of the system tables are setup correctly. This program is usually invoked by other programs as part of installation, but in the case of .tar.gz downloads will need to be executed manually.

As part of our ongoing efforts to refactor and improve MySQL, we are looking at converting mysql_install_db from its current Perl script to a program written in C++. The aim of this change is to reduce external dependencies (Perl + a set of modules) and improve our cross-platform experience.

We plan for this transition to be mostly function neutral, but are open to feature requests for additional improvements as well.

Have you worked in packaging MySQL?
Do you have any suggestions on how mysql_install_db can be improved?
Please leave a comment, or get in touch!

We’re looking to improve PlanetMySQL

We are looking for community feedback on how improve the Signal-to-Noise ratio of PlanetMySQL, and reduce the amount of irrelevant and off-topic posts.

To give you a sense of where we are at today, we currently approve most [all?] blogs for aggregation, provided they have some existing technical content. We then apply a naive regular expression to make sure that all posts are on topic (MySQL).

The sorts of ideas we are looking for are:

  • What content are you interested in seeing more or less of?
  • What posts do you deem as acceptable or unacceptable?
  • Do we need to change the balance between technical, marketing, event, or business-related posts?
  • Are there any tools or features we could introduce to better serve readers and authors?

If you have any suggestions – please send them my way!

Five reasons why vertical scalability matters

The latest benchmarks show that MySQL 5.7 is now able to scale to 60 cores, which is quite an incredible feat when you compare to the 4-8 core scaling of MySQL 5.1 just a few years ago. These improvements are the result of a lot of heavy lifting to reorganize internal locking structures, and I have an earlier blog post on what is a mutex anyway? which may help serve as an introduction.

While I consider horizontal scaling and projects like MySQL Fabric to be very important, it should be stated that horizontal and vertical scaling are really orthogonal choices. That is to say that a given database technology should ideally support both options, and today I wanted to zoom in on some of the advantages I see with being able to scale vertically:

  1. Having more cores offers more consistent performance. Think of a single CPU as like shopping at a convenience store with one person on the checkout. The experience is very good when there is nobody else in line, but it degrades very quickly when just a couple of shoppers are lined up before you.

    To add to that, even if you know that there are an average of 60 customers per hour, you can not expect them to arrive at an equal distribution of one customer per minute. What usually happens is a more random pattern (see Poisson distribution) of arrivals.

    The solution to this problem is to have more staff available at the checkout. The more staff available, the less variance in the time that it takes to serve a customer. Similarly, having multiple CPUs means that query times will degrade much nicer as there are subtle spikes in load.

  2. Simplified debugging and performance characteristics. For some applications, where the lifetime growth requirements can be answered by a single server (or single master, multiple HA slaves), having a single primary server can be beneficial.

    The number of transactions/second that a single-server can now respond to is also much higher than it used to be. Dimitri’s 5.7 Sysbench OLTP_RW shows 15K transactions/second (or over 500K point select queries/second), and prematurely introducing architectural-complexity through horizontal scaling may increase the effort required to troubleshoot problems. In some cases it may also artificially prevent desirable features such as strong consistency (ACID).

  3. Good insurance for the unknown. Some applications grow in unexpected ways, and being able to scale up offers a great upgrade path that is less likely to change performance characteristics than horizontal scaling, and require fewer application changes.

    Often the cost of higher-end commodity hardware is less than that of custom-development time. I once experienced the case where a legacy application that was planned for decommission started having performance problems. Paying for the biggest EC2 instance type was worth it for a few months, and we probably would have paid more if other options were available (they were not at the time, but are now).

  4. Increased efficiency at scale. That is to say that even with automation, it is easier to manage 1000 16-core instances than it is to manage 16000 single core instances.

  5. An alternative consolidation strategy to virtualization. For some organizations, backing up and maintaining many small database servers presents operational complexity, even when the underlying servers lie on virtualized hardware. Having a larger single database instance with many database schemas can offer an alternative that may be easier to manage.

    I concede that there is some functionality missing on the MySQL-side to truly realize this potential, since it would be nice to be able to set more fine-grained quotas per application and limit the ability to accidentally Denial of Service other applications. However, some headway has been made with performance_schema now able to instrument things that were previously not possible. Most notably, in MySQL 5.7, memory can now instrumented per user.

Conclusion

I wanted to close with an example of how the horizontal and vertical should work together. Lets say that you operate a SaaS application with millions of users, and have the option to either massively-shard or use a single larger server. Both options may be sub-optimal:

Vertical Scaling Horizontal Scaling

PRO: Having vertical scalability allows each user to have some burstable performance that can be absorbed by larger hardware.

CON: It is possible that an extremely busy users will impact all other users, creating an all-eggs-in-one-basket scenario.

PRO: Multiple horizontal shards allows some natural fencing where the extreme spikes can be contained to group of users. This assumes that indivual users do not need cross-shard queries, otherwise it hinges on my point above under “Simplified debugging and performance characteristics”.

CON: If the application is excessively horizontally scaled, some of the busier users may have a bad experience as their shard becomes overloaded too quickly. Quite often these busy users can be the ones with the most revenue associated to them.

By horizontally scaling across many vertically scalable servers, you can get closer to get the best of both worlds.

Installing MySQL 5.6 on Ubuntu 14.04 (Trusty Tahr)

Ubuntu 14.04 defaults to MySQL 5.5, but also has MySQL 5.6 available for installation from the universe archive. Installing 5.6 is as easy as specifying the version, apt-get install mysql-server-5.6:


root@ubuntu1404:~# apt-get install mysql-server-5.6
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
libaio1 libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18 libterm-readkey-perl mysql-client-5.6 mysql-client-core-5.6 mysql-common
mysql-common-5.6 mysql-server-core-5.6
Suggested packages:
libclone-perl libmldbm-perl libnet-daemon-perl libplrpc-perl libsql-statement-perl libipc-sharedcache-perl mailx tinyca
The following NEW packages will be installed:
libaio1 libdbd-mysql-perl libdbi-perl libhtml-template-perl libmysqlclient18 libterm-readkey-perl mysql-client-5.6 mysql-client-core-5.6 mysql-common
mysql-common-5.6 mysql-server-5.6 mysql-server-core-5.6
0 upgraded, 12 newly installed, 0 to remove and 0 not upgraded.
Need to get 21.5 MB of archives.
After this operation, 164 MB of additional disk space will be used.
Do you want to continue? [Y/n] Y
Get:1 http://mirrors.digitalocean.com/ubuntu/ trusty/main libaio1 amd64 0.3.109-4 [6,364 B]
Get:2 http://mirrors.digitalocean.com/ubuntu/ trusty/main mysql-common all 5.5.35+dfsg-1ubuntu1 [14.1 kB]
Get:3 http://mirrors.digitalocean.com/ubuntu/ trusty/main libmysqlclient18 amd64 5.5.35+dfsg-1ubuntu1 [593 kB]
Get:4 http://mirrors.digitalocean.com/ubuntu/ trusty/main libdbi-perl amd64 1.630-1 [879 kB]
Get:5 http://mirrors.digitalocean.com/ubuntu/ trusty/main libdbd-mysql-perl amd64 4.025-1 [99.3 kB]
Get:6 http://mirrors.digitalocean.com/ubuntu/ trusty/main libterm-readkey-perl amd64 2.31-1 [27.4 kB]
Get:7 http://mirrors.digitalocean.com/ubuntu/ trusty/universe mysql-client-core-5.6 amd64 5.6.16-1~exp1 [4,084 kB]
Get:8 http://mirrors.digitalocean.com/ubuntu/ trusty/universe mysql-client-5.6 amd64 5.6.16-1~exp1 [5,591 kB]
Get:9 http://mirrors.digitalocean.com/ubuntu/ trusty/universe mysql-server-core-5.6 amd64 5.6.16-1~exp1 [4,333 kB]
Get:10 http://mirrors.digitalocean.com/ubuntu/ trusty/universe mysql-server-5.6 amd64 5.6.16-1~exp1 [5,839 kB]
Get:11 http://mirrors.digitalocean.com/ubuntu/ trusty/main libhtml-template-perl all 2.95-1 [65.5 kB]
Get:12 http://mirrors.digitalocean.com/ubuntu/ trusty/universe mysql-common-5.6 all 5.6.16-1~exp1 [14.9 kB]
Fetched 21.5 MB in 5s (3,760 kB/s)
Preconfiguring packages ...
Selecting previously unselected package libaio1:amd64.
(Reading database ... 59014 files and directories currently installed.)
Preparing to unpack .../libaio1_0.3.109-4_amd64.deb ...
Unpacking libaio1:amd64 (0.3.109-4) ...
Selecting previously unselected package mysql-common.
Preparing to unpack .../mysql-common_5.5.35+dfsg-1ubuntu1_all.deb ...
Unpacking mysql-common (5.5.35+dfsg-1ubuntu1) ...
Selecting previously unselected package libmysqlclient18:amd64.
Preparing to unpack .../libmysqlclient18_5.5.35+dfsg-1ubuntu1_amd64.deb ...
Unpacking libmysqlclient18:amd64 (5.5.35+dfsg-1ubuntu1) ...
Selecting previously unselected package libdbi-perl.
Preparing to unpack .../libdbi-perl_1.630-1_amd64.deb ...
Unpacking libdbi-perl (1.630-1) ...
Selecting previously unselected package libdbd-mysql-perl.
Preparing to unpack .../libdbd-mysql-perl_4.025-1_amd64.deb ...
Unpacking libdbd-mysql-perl (4.025-1) ...
Selecting previously unselected package libterm-readkey-perl.
Preparing to unpack .../libterm-readkey-perl_2.31-1_amd64.deb ...
Unpacking libterm-readkey-perl (2.31-1) ...
Selecting previously unselected package mysql-client-core-5.6.
Preparing to unpack .../mysql-client-core-5.6_5.6.16-1~exp1_amd64.deb ...
Unpacking mysql-client-core-5.6 (5.6.16-1~exp1) ...
Selecting previously unselected package mysql-client-5.6.
Preparing to unpack .../mysql-client-5.6_5.6.16-1~exp1_amd64.deb ...
Unpacking mysql-client-5.6 (5.6.16-1~exp1) ...
Selecting previously unselected package mysql-server-core-5.6.
Preparing to unpack .../mysql-server-core-5.6_5.6.16-1~exp1_amd64.deb ...
Unpacking mysql-server-core-5.6 (5.6.16-1~exp1) ...
Processing triggers for man-db (2.6.7.1-1) ...
Setting up mysql-common (5.5.35+dfsg-1ubuntu1) ...
Selecting previously unselected package mysql-server-5.6.
(Reading database ... 59386 files and directories currently installed.)
Preparing to unpack .../mysql-server-5.6_5.6.16-1~exp1_amd64.deb ...
Unpacking mysql-server-5.6 (5.6.16-1~exp1) ...
Selecting previously unselected package libhtml-template-perl.
Preparing to unpack .../libhtml-template-perl_2.95-1_all.deb ...
Unpacking libhtml-template-perl (2.95-1) ...
Selecting previously unselected package mysql-common-5.6.
Preparing to unpack .../mysql-common-5.6_5.6.16-1~exp1_all.deb ...
Unpacking mysql-common-5.6 (5.6.16-1~exp1) ...
Processing triggers for ureadahead (0.100.0-16) ...
ureadahead will be reprofiled on next reboot
Processing triggers for man-db (2.6.7.1-1) ...
Setting up libaio1:amd64 (0.3.109-4) ...
Setting up libmysqlclient18:amd64 (5.5.35+dfsg-1ubuntu1) ...
Setting up libdbi-perl (1.630-1) ...
Setting up libdbd-mysql-perl (4.025-1) ...
Setting up libterm-readkey-perl (2.31-1) ...
Setting up mysql-client-core-5.6 (5.6.16-1~exp1) ...
Setting up mysql-client-5.6 (5.6.16-1~exp1) ...
Setting up mysql-server-core-5.6 (5.6.16-1~exp1) ...
Setting up mysql-server-5.6 (5.6.16-1~exp1) ...
2014-04-21 11:50:07 0 [Warning] Using unique option prefix key_buffer instead of key_buffer_size is deprecated and will be removed in a future release. Please use the full name instead.
2014-04-21 11:50:07 0 [Warning] TIMESTAMP with implicit DEFAULT value is deprecated. Please use --explicit_defaults_for_timestamp server option (see documentation for more details).
mysql start/running, process 2355
Setting up libhtml-template-perl (2.95-1) ...
Setting up mysql-common-5.6 (5.6.16-1~exp1) ...
Processing triggers for libc-bin (2.19-0ubuntu6) ...
Processing triggers for ureadahead (0.100.0-16) ...

And then:


root@ubuntu1404:~# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 45
Server version: 5.6.16-1~exp1 (Ubuntu)

Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select version();
+---------------+
| version() |
+---------------+
| 5.6.16-1~exp1 |
+---------------+
1 row in set (0.00 sec)

Update: A slightly more detailed tutorial for this is available here. Thank you internet!

MySQL 5.6.17 Community Release Notes

Thank you to the MySQL Community, on behalf of the MySQL team @ Oracle. Your bug reports, testcases and patches have helped create a better MySQL 5.6.17.

In particular:

  • Thanks to Anthony Pong for reporting a confusing error message when mysql_install_db could not locate the required Perl modules. Bug #69844.
  • Thanks to Jervin Real for reporting a recently introduced performance regression with compressed InnoDB tables. Bug #71436.
  • Thanks to Laurynas Biveinis for reporting a race condition in InnoDB on shutdown. Bug #70430.
  • Thanks to Jervin Real for reporting that innodb_data_file_path could not be specified in kilobytes, as was indicated in the manual. Bug #68282.
  • Thanks to Elena Stepanova for reporting that InnoDB miscalculates auto-increment after changing auto_increment_increment. Bug #65225.
  • Thanks to qinglin zhang for reporting a memory leak in the slave sql thread, plus providing a suggested patch. While we did not end up using qinglin’s patch, we value the contribution. Bug #71197.
  • Thanks to 徹 赤松 for reporting that SHOW SLAVE STATUS incorrectly reported the master’s SSL information. Bug #70866.
  • Thanks to Yoshinori Matsunobu for reporting an issue where a slave can’t continue replication after the master’s crash recovery Bug #70669
  • Thanks to Erik Hoekstra for pointing out that using slave-parallel-workers may result in the error log being spammed with warnings. Bug #68429.
  • Thanks to Ovais Tariq for identifying that slaves with an additional auto-increment were not updated correctly. Bug #69680.
  • Thanks to Simon Mudd for suggesting that modifications to performance_schema tables should not be replicated. Bug #67159.
  • Thanks to Miguel Angel Nieto for identifying that temporary files created by binlog cache are not cleaned up. Bug #66237.
  • Thanks to hickey liu for reporting a race-condition in semi-sync replication. Bug #66411.
  • Thanks to Yoshinori Matsunobu for reporting excessive mutex contention in semi-sync replication. Bug #70218.
  • Thanks to honza horak for suggesting that mysqld –help should exit with a zero error code. Bug #70058.
  • Thanks to Jonathan Weaver for identifying that MySQL community edition client programs could not connect to MySQL enterprise servers with SSL enabled. Bug #68788.
  • Thanks to Jørgen Thomsen for reporting that mysqldump did not support the secure-auth parameter. Bug #69051.
  • Thanks to Raghavendra Prabhu for reporting an assertion when running Random Query Generator (RQG). Bug #69969.
  • Thanks to Tim McLaughlin for reporting that wrong results could be returned in a SELECT DISTINCT…GROUP BY query. We also thank Tim for reducing the bug to a minimal testcase. Bug #70657.
  • Thanks to Hartmut Holzgraefe for suggesting improvements to warnings written to the error log for invalid collations. Bug #68144.
  • Thanks to Ralf Adams for reporting that wrong results could be returned when using ALL() and GROUP BY. Ralf also provided a minimal testcase, which was useful in reproducing the issue. Bug #71244.
  • Thanks to Elena Stepanova for identifying that unquoted file names for variable values are accepted but parsed incorrectly. Bug #69703.
  • Thanks to Valeriy Kravchuk for suggesting that innodb_ft_result_search_limit should have a predictable maximum value. Bug #71554.

Thank you again to all the community contributors listed above. In particular, the MySQL team would like to call out the names that appear more than once in this release:

Jervin Real (2), Yoshinori Matsunobu (2), Elena Stepanova (2)

If I missed a name here, please let me know!

- Morgan