Oracle Corporation (ORCL)
NYSE: ORCL · Real-Time Price · USD
148.56
+0.95 (0.64%)
At close: Sep 21, 2026, 4:00 PM EDT
149.08
+0.52 (0.35%)
After-hours: Sep 21, 2026, 7:59 PM EDT
← View all transcripts

Status Update

Nov 24, 2015

Luís Soares
MySQL Replication Team Lead, Oracle

Hi, my name is Luís Soares, I'm the MySQL Replication team lead at Oracle and have been for a few years now. Today, I'll be talking to you about the new replication features in MySQL 5.7. There'll be time at the end of the session for question and answers, but feel free to fire away your questions while the session is ongoing. Let me just give you a few seconds for you to go through the safe harbor statement. This is the agenda for today's session. I will start by celebrating the fact that MySQL 5.7 is GA. It has GA'd recently, and together with it, the replication framework. I will talk a little bit about what MySQL replication actually is, showcase its building blocks and so on, to give you an overview on how it works and what it actually is.

We'll dive into the new replication features into MySQL 5.7. After that, I will talk a little bit about the work that we have ongoing by presenting some of the feature previews that we have on labs.mysql.com. In the end, I will conclude the session by trying to give you an overview of our roadmap. Here are some interesting facts about MySQL 5.7 replication in particular. There were 40 replication work logs pushed to MySQL 5.7. Work log is a unit of work, and usually this means that we implemented this amount of work to create the new features. We have merged eight contributions into MySQL 5.7 replication. In total, we have 19 major enhancements to the replication core and 14 refactorings and modularization-related work that was also done in the code base.

In addition to this, we have this one new entirely out-of-core replication plugin that we call MySQL Group Replication. Still on labs, but exhibiting a very fast, rapid release rate. We actually want to thank you. After two and a half years of being in the making, the team is very happy to actually present what we have been doing to all of you and giving you this for you to use. Thank you for being part of it. A lot of you guys have actually contributed in one way or another, either through bug reports, feature requests, contributions, and so on. We seriously hope that you enjoy MySQL 5.7, in particular, the new replication features in it. MySQL replication is very simple in its architecture.

There's basically one server that takes incoming updates, usually called the master, and then there's one or more servers that actually copy these updates from the master and install them in their local databases. These servers are often called the slaves. To make it all work, there's a log that is being moved around. This log captures the changes on the master and is used on the slave to replay them against its local database. This log is usually called the binary log. In this process, there's a bunch of threads involved. On the master side, there's a sender thread per slave connected, and on the slave side, there's a receiver thread, and a bunch of apply threads that actually apply the binary log against the local database. The binary log is an important part of the MySQL replication architecture.

It captures the changes that have happened on the master side. These changes in this file are copied to the slave. The slave uses the same binary log infrastructure to apply the changes to its local database. Changes are captured on the master side, either in statement format, in which case the slave has to replay these statements against its local database, or in row format, which is basically a binary representation of the rows that were changed. In this case, the slave will install these changes to its local database. Apart from data-related events or units in the binary log, there are also control events, which basically are related to the fact that the server needs to know when a binary log is rotated, what's the format of the binary log, and so on. Replication can be used for read scale out.

Imagine that you're building your business, you're deploying your databases, you have opened your web shop, you have incoming loads. Your business starts to grow, and you want to offload the master by redirecting read queries to some other server. For this, you can deploy a slave. Your slave will be continuously copying changes from the master, so you can do something like read/write splitting. Once your business starts to grow, it could be that your reads is taking a lot of your slave capacity already, so you might want to deploy more and more slaves so you can achieve read scale-out in this case. There's also write scale-out. Write scale-out is not really addressed by MySQL replication. The fact is that there is MySQL Fabric that could actually help in this case by sharding your data.

We will not cover this in this presentation. It's also used for HA, for having means to provide a redundant MySQL service. In this case, we have here depicted a master and two slaves. If the master crashes, we can make one of the slaves to be the new master and allow the service to continue without minimal disruption. Another typical example is to do some sort of online backup and also to do reporting or to rely on the slave to actually make these very big reporting queries without interfering with the performance of the master. It's also useful for doing replication between data centers. This is interesting because it can be used for deploying solutions for disaster recovery. Let's dive into the new replication features in MySQL 5.7.

I'll split the new replication features throughout different areas. The first one I'll address is usability and more online operations. There was a lot of work put into this area. The first one is online reconfiguration of Global Transaction Identifiers. Global Transaction Identifiers is a feature that was introduced in MySQL 5.6 and allows a new positioning scheme in the replication stream for both masters and slaves. The fact is that this positioning strategy is incompatible with the old and traditional one, which relies on file names and positions inside the file. Ultimately, this means that to turn on this feature in MySQL 5.6, the user has to incur in some sort of offline, because it has to synchronize all the servers before it can switch on the new Global Transaction Identifiers in the replication stream.

As such, to overcome this problem of having to synchronize the servers and then introducing some offline period in your system, MySQL 5.7 provides this procedure to turn the feature on online. When the procedure is ongoing, both reads and writes are allowed into the system, and there's no need to synchronize the servers ever. No need to restart servers, no need to actually change the topology as well. The fact is that this procedure works in arbitrary topologies. There was a big effort put into this to allow this procedure to be crash-safe in the sense that should anything wrong happen in the middle of the migration, let's call it that, in the middle of this migration procedure, the user can always roll back the changes. At its core, the procedure is very simple.

We have to go through stages to go from off to GT mode on, so no global transaction IDs at all to global transaction IDs always. The fact is that we have to go through these stages to allow different positioning schemes to coexist in the same replication stream. We're slowly morphing through these stages from old style positioning to the new style positioning. Anyway, the procedure is completely detailed on this reference manual page here, so feel free to have a look at it. We also have online reconfiguration of replication filters. It used to be the case that to change the replication filters, one would need to restart the server, and that's not the case anymore in MySQL 5.7. We can change the replication filters dynamically by issuing this command here, CHANGE REPLICATION FILTER, replication_db.

In this case, we're exemplifying with the replication_db, but it also is applicable to all slave filters. The fact is that you just need to stop the replication threads, change the filters, and restart the replication thread. There's no need to restart the entire server anymore. We have also introduced this online reconfiguration of replication receiver and applier threads separately. I'll go into the details. Imagine that there is a replication topology just like this one, a master and two slaves, and the master crashes. Then you want to promote one of the slaves to take A's role, so one of the slaves will become a master. In this case, the new master is B. Then one can failover C's receiver thread from A to B without having to stop C's applier threads. Thus, this enables more online operations during failover procedures.

One can change the master without having to stop applier threads. The opposite or the reverse is also true. We can change applier configuration without actually having to stop the receiver threads. In this case, what is shown here is that we are changing the delayed slave period to 3,600 without having to stop the IO thread or the receiver thread. We have also worked quite a bit on improving the replication monitoring in MySQL 5.7, in particular, the slave side of it. We worked quite a bit in MySQL 5.7 to instrument the slave side replication framework and then expose the data collected through this instrumentation, through Performance Schema replication tables.

These tables also allows us to more consistently and seamlessly integrate the monitoring of new features like multi-source replication or MySQL Group Replication, where in this case, SHOW SLAVE STATUS was, for instance, fall short or not scale at all. We took this opportunity to group logically related information instead of having it all in one place. This resulted in six different replication Performance Schema tables. As you can see here, there's a table for connection configuration, connection status, applier configuration, applier status, applier coordinator status, and worker status. Given these tables, one can actually inspect what each worker thread is doing. In this case, we can see, for instance, which global transaction identifier some worker thread has actually processed, applied recently. We can also find out if a worker thread errors out, why does it error out, as you can see in these fields here.

Improving replication performance, that's another area that we focused a lot in MySQL 5.7. Let's start by talking about improved applier throughput, which basically impacts both the master and the slave. It impacts the master because the master has to put some extra information into the binary log for the slave to be able to schedule transactions in parallel in a more optimal way. Before I delve into the details, let me just say that in our internal benchmarks, we have observed a 10 times throughput improvement when comparing the multi-threaded slave applier against the single-threaded applier. This, of course, is possible because the multi-threaded slave is applying more transactions in parallel when the single-threaded applier is applying one by one.

It also shows that the slave makes good use of the information that the master puts into the binary log, when it comes to deciding which transactions can be scheduled in parallel. Under the hood, what happens is that the master puts into the binary log which transactions have executed concurrently and have not blocked each other. The slave takes this information, and if any two transactions have not blocked each other on the master during their execution, they will be scheduled in parallel. To illustrate this procedure, let's consider this example here. We have three transactions running on the master, and T1 is executing first. It starts committing, and immediately after, T2 also starts committing. The point here is that T2 starts committing before T1 finishes its commit. This means that T2 was actually never blocked by any of T1's locks.

T3, on the other hand, starts committing after T1 has already finished its commit and released its lock, we don't really know whether T3 was blocked by T1 or not. The interesting point, though, is that T3 was not blocked by any of T2's locks, since T2 has not yet finished its commit when T3 started committing. Ultimately, what this means is that the slave can schedule T1 and T2 in parallel. Not T1, T2, and T3. The slave can schedule T3 in parallel with T2 after T1 has finished its execution. In a way, this creates the concept of a sliding window that the slave can use to parallelize transactions when they are to be applied. This new multi-threaded applier scheduling policy supports both replication formats. Whether one is replicating as statements or row format, it will work.

The scheduling policy itself can be controlled using this system variable, slave_parallel_type. One can set it to logical clock, which is the new scheduling policy, or database, which is the old scheduling policy from MySQL 5.6. Although these performance results are already quite promising, when we talk about performance development or improving performance, we usually refer to a highly iterative and highly repetitive process. A lot of pain points, a lot of scalability issues that one had to deal with. The fact is that we expect that this work doesn't stop here. It will continue as we introduce new features, as we improve MySQL replication framework in 5.8 and so on. This is really interesting work that is happening. We have also worked quite a bit on the user and sender thread synchronization.

The fact is that when a session is executing a transaction and writing to the binlog, it has to compete with the sender threads for a resource, this resource meaning the binary log itself. Therefore, we work to make the synchronization between these different types of threads in such a way that allows concurrent reads while the user sessions are writing to the binary log. This removes a scalability pain point around the binary log resource. We have also done some large refactoring on the sender thread. This enabled to deploy a better memory management on its own data structures, as well as removing some scalability issues. Ultimately, what this means is that even though the send buffer is still dynamic, it is not allocated and freed every time an event is sent. Instead, we have the buffer to be adaptive with respect to the workload.

The buffer grows and shrinks according to some metrics, depending on the workload that is being pushed, depending on the event load that is being pushed into the slave. This change, together with some enhancements that I've mentioned before, increase the master scalability, reduces CPU consumption, and copes with the better peak load. If we have a peak of load, the buffer will grow and slowly shrink once the peak is over. We've done some micro benchmarks to measure the impact of our changes in the sender thread. What we found in our micro benchmark is that the master is able to sustain the throughput as we connect more slaves to it.

In this case, we're comparing 5.6.16 against 5.7.4, and you can see that around 30 slaves, when we had 30 slaves connected to the master, you can see 5.6.16 already having some difficulties keeping up with this fact, while 5.7.4 is able to sustain the throughput, even though it has more slaves connected to it. Another area that we spent some of our effort on was on semi-synchronous replication, in particular to make it fast or faster. For this, we deployed this acknowledgment receiver thread that is only responsible to collect the acknowledgments from the slave and notify those sessions that are waiting for an acknowledgment to resume. This means that the sender thread is not responsible for receiving the acknowledgments anymore and can push the binary log to the slave as fast as it can.

In practice, this means that consecutive transactions do not block each other while waiting for acknowledgment. The sender thread is able to send T1 and T2, then the acknowledgment thread will be responsible for receiving the acknowledgments, as opposed to the sender thread sending T1 first, waiting for the acknowledgment, then sending T2, then wait for the acknowledgment back. The thread, the acknowledgment receiver thread, starts once semi-sync is activated implicitly. It also stops when we deactivate semi-sync. Given all the improvements on the sender thread and on semi-sync Performance allows us to think about moving the durability of our data from the local disk to the replication itself. If I'm okay with considering changes durable, as long as they are on my master and on my slave, then I can, for instance, disable all the fsyncs to local disk.

In the event of the master crashing, I can go to the slave, since my changes were semi-synced to the slave, I can get my changes from the slave instead. While we were doing some of these benchmarks, comparing semi-sync durability to disk durability, we actually found out that relying on semi-sync for durability or replication for durability, in this case, we could get a lot of more throughput on the master side in some cases. This is what this figure is depicting here. The third area that I want to highlight that we have worked on in MySQL 5.7 is dependability. In the original semi-synchronous replication, as it was introduced in 5.5 and 5.6, there is a possibility that some changes are externalized by concurrent sessions, while the original session that actually made the change is waiting for an acknowledgment.

This could lead potentially to a lost update situation, in which case, for instance, the master crashed while the session was waiting for the acknowledgment from the slave and some concurrent read operation had already externalized the change. We worked in 5.7 to make this go away. This is depicting what happens in MySQL 5.7 today. We can see here two transactions. One is an insert and the second one is a select. The insert executes, prepares, is written to the binlog, to the binary log, then it is sent to the slave, and only when the slave acknowledged back, we commit the transaction in the storage engine. At that point in time, we externalize the changes made by T1. Before this change, in 5.5 and 5.6, T2 could externalize the insert already before the acknowledgment is received from the slave.

This would happen because the waiting would happen after the commit was done and not before. In 5.7, we wait between the point in time that we write the changes to the binary log and the point in time that we commit the transaction to the storage engine. Any concurrent read operation will not externalize the data at that point in time. In practice, as I said, master waits for the act before committing as opposed to master waiting for the slave's act after committing. Should the master fail, then any transaction that it may have externalized is already persisted on the slave. This also means that even if I have not externalized the transaction on the master, there's also the possibility that it is already transferred to the slave at the moment that the master crashed.

The user can choose between the original semi-synchronous behavior and the new semi-synchronous behavior by setting this option, rpl_semi_sync_master_wait_point. You can set it to after sync, which basically is the new behavior, and to after commit, which is the old behavior from 5.5 and 5.6. In semi-sync replication, we deployed this infrastructure for waiting for multiple acknowledgments instead of just one. If a transaction wants to wait for more than one ACK before it resumes the commit, it can set the number of acknowledgments it wishes to wait for. In practice, the master does not commit a transaction until it gets N acknowledgments from N slaves. This is dynamically settable through this system variable, rpl_semi_sync_master_wait_for_slave_count. If you set it to N, then you need N acknowledgments before the transaction is actually committed. This is a diagram depicting what actually happens under the hood.

There's a master and three slaves, three semi-sync slaves, then there's a transaction one coming in, which requested two slaves to acknowledge before the session is released to the application. Once C1 commits or asks for a commit, the changes in the binary log are replicated to the slaves. Two of them will acknowledge back, and at that point in time, the master will release the session to resume. That's pretty much it. Flexibility, also an interesting area that we worked on in MySQL 5.7, making it work in a lot more use case scenarios, making it be more flexible and adjustable to different kind of use cases. When we introduced Global Transaction Identifiers in MySQL 5.6, we actually introduced a major feature, or actually, a major feature set. Global Transaction IDs is more of three things packed together. It's a Global Transaction Identifier itself.

It's the auto-skipping procedure. If a server has handled a transaction, it is able to know that it has handled it, and it will auto-skip the same transaction if the user will wrongly try to resubmit it. It's also the auto-positioning protocol between masters and slaves, which allow slaves and masters to automatically negotiate which parts of the replication stream a slave is missing. This is all good, but along with this came a set of requirements as well. One of these requirements is the fact that if a slave wants to use auto-positioning protocol and Global Transaction IDs, it has to have the binary log on in MySQL 5.6.

This works for a lot of our users and doesn't work so well for some of our other users, which would prefer the slave not to have the binary log on because these slaves will never be candidate slaves. They will never be candidates to replace the master in case of the master crashes. They would rather like to use the auto-positioning but not have to have the binary log on. This is what we have worked on in MySQL 5.7. Starting in MySQL 5.7, the slaves can use GTIDs when the binary log is disabled. As I said, these slaves not having the binary log means that they will never be candidate slaves to replace the master, in the sense that they can not serve previous replication history because they don't have their own binary logs.

They still, at the same time, they still can use Global Transaction IDs to actually do the auto-positioning. To make it all work without having the binary log on the slave, we need to save the Global Transaction ID's execution history somewhere. This somewhere, this place where we store the Global Transaction ID's execution history, is actually a system table called mysql.gtid_executed. You can see on this slide the scheme or the structure of this table, which is basically a table with three fields: source_uid, interval_start, and interval_end. Global Transaction IDs are inserted into this table as transactions commit, and periodically, a range compression thread runs and compresses all these records in the table into a single range. The period of this thread is dynamically configurable using this system variable, gtid_executed_compression_period=N. N being the number of transactions between the decompression procedure runs.

There are some details to this procedure of storing Global Transaction IDs in a table. What happens if my binary log is enabled? Will the table be filled or not? What happens if I don't assign a Global Transaction ID to a transaction and the binary log is disabled? Will this transaction get a Global Transaction ID assigned to it or not? To answer these questions, let me just make it clear that if the binary log is enabled, transaction or Global Transaction IDs are stored in the binary log. On rotation of the binary log, these transaction IDs that were written to the binary log that is being rotated are copied into the system table. This was to reduce the performance impact of storing transaction IDs or Global Transaction IDs into the binlog and the table at the same time.

If the binary log is disabled, we store Global Transaction IDs in a table transactionally. New transactions are not assigned a Global Transaction ID if GTID assignment is set to automatic, because these transactions are local transactions. They don't exist anywhere else. It's kind of meaningless assigning them a Global Transaction ID. The key point, the key takeaway from this slide is that we always store Global Transaction IDs transactionally, and this means that the process of storing transaction identifiers is crash safe. If there's a crash, we will always recover the data together with the Global Transaction ID. Another big feature in MySQL 5.7 is multi-source replication. Traditionally, or since the beginning of the times in MySQL replication universe, the user can only set up replication from one master to multiple slaves, kind of like a fan-out replication scheme.

With MySQL 5.7 replication, you can have a server aggregating or pooling data from multiple masters. In a way, a slave can have multiple masters. This is great because it allows some different workflows for replication or enables some different workflows using MySQL replication. Some of the use cases that may be covered by this feature are integrated backups, aggregating multiple different parts of your data that are scattered throughout different servers, aggregate them all into a single server and then back everything up from there. Having multiple shards of your data spread out as well across different servers, and then you want to run cross-shard operations. You can aggregate them in a single server and then run your complex queries there.

For instance, acting as a single hub for inter-cluster replication, pushing all of your data in your data center into some server and then replicating across wide area through that server. To sum it up, a server can replicate from multiple sources, and for each source, there's an instance of the slave replication framework, which we call a channel. A channel is a receiver thread, a relay log, and a set of applier threads. These channels can be operated or configured separately. With multi-source replication, we have also support for inspecting each slave instance, each channel instance separately through the new replication Performance Schema tables. We have things like replication applier status by coordinator, which shows multiple entries, one row per channel. The same thing goes for replication applier status by worker, and the same thing for replication connection status.

Multiple records, multiple rows on these tables showing stats for each channel. This source replication is also integrated with GTIDs. It's integrated with crash safe tables, and there's virtually no limit of the numbers of sources that a slave can have or a server can have. However, we have capped it in the source to 256. If you're building the MySQL server yourself and you need to have more than 256 sources, you can just search for the variable that defines this limit and change it to your liking. As I said, we're able to manage each source separately. Through the change master command, you can add a clause for specifying on which channel that change master command will operate on.

There's also a bunch of new features and improvements that I was not able to fit on any of these previous categories, but they are still interesting to mention. Let's just quickly go through them. Here's the list. This is the list with the smaller and yet interesting enhancements. Let me just quickly go through it then. There's an enhancement to the multi-threaded applier, which makes it able to retry failed transactions. This was not the case in MySQL 5.6, this is fixed in 5.7. There's an option as well to make the multi-threaded applier preserve the commit order. The order that transactions appear on the relay log, they will be committing under that order. There's also some work done in the MySQL binlog tool. Basically, we have new options, new SSL options, and also an option to rewrite DB when outputting row events.

There's also a very interesting function, global transaction ID function, related function, which makes the session wait until a given set of transaction IDs has been processed by that server. There's also an option to track which transaction ID was generated as part of this transaction, and this information is reported back in the OK packet of the MySQL protocol. There's also support for XA transactions when the binary log is on. There was a lot of work done in the XA framework in 5.7, including in the replication framework. Now, when a user does an XA transaction and prepares it and then disconnects, this is preserved even if the binary log is enabled. Then there's this noticeable change or notable change to the defaults with respect to the binlog format and sync_binlog.

The binlog format is now row by default, sync_binlog is set to one by default as well. Finally, there are some interesting options to fine-tune the binary log group commit procedure. We can have delays, we can tweak it to better fit our workload and then this also has impact on the amount of parallel transactions that can be marked as parallel on the master and then scheduled in parallel on the slave. It can have impact on the throughput on the slave as well. Let me just talk a little bit about an interesting piece of infrastructure that has been declared GA also very recently, and that goes almost hand-in-hand with replication. Let's start. We have the MySQL Router, which has recently been declared GA.

The motivation to have created this piece of infrastructure was mostly driven by the fact that we wanted to interact with Fabric without having to have to upgrade existing connectors or even allow users that have or use connectors that do not support Fabric at all to be able to use it anyway. It's also one piece of infrastructure that hides the complexity associated with read-write splitting and automatic failovers from the application itself. The router acts as an entry point to our replicated system where all these things are happening. From the very beginning, the MySQL Router was designed while keeping performance and flexibility in mind. It has a very good performance, and it has a plugin-driven architecture so that it is easily extensible.

From the feature set, let me just highlight that the router provides a connection-based routing and simple load balancing, and also does seamless failover based on Fabric HA groups. When it coupled together with Fabric, you can automate failovers without having to expose that to the application. Let me just go briefly through what we have been doing, and we have been releasing on labs.mysql.com. We have on labs a very exciting new replication plugin called MySQL Group Replication Plugin. It provides multi-master update everywhere, meaning different clients can update the same role on different servers at the same time, and this will be handled. This replication plugin also provides automatic group membership management and failure detection, and there's no need for server failover because they are pretty much every one of them is a master and they act as a group.

It provides also automatic reconfiguration, no single point of failure, and it is a shared nothing state machine replication, every server has a copy of the entire database itself. It is InnoDB compliant. Basically you have all the look and feel from InnoDB and MySQL that you are used to, and you can deploy this in off-the-shelf hardware. This is a great technology for deployments where elasticity is a requirement. For instance, cloud-based infrastructures, and the fact is that it is very well integrated with all different features in replication. It has some requirements. For instance, it requires global transaction IDs and global transaction replication, and you can monitor it through Performance Schema table as well. It is elastic and self-healing in the sense that you can add and remove nodes, and the group will notice that.

When a node is removed, the group will notice that it is gone. If you add a server, the group will realize that the new server is joined, and the server will automatically transfer the missing state, the missing binary logs. As you can see here, it has had a strong development cycle, lots of releases in one year on labs, and we're happy to say that it has seen a very strong community engagement, very strong feedback from different parts of the community. A couple of side notes here. With MySQL Group Replication Plugin for 5.7.9, we have introduced a new group communication engine. Corosync is not needed anymore, and the full MySQL Group Replication Plugin stack is self-contained in the plugin itself. Another interesting fact is that the plugin now builds on multiple platforms, it's not constrained to Linux anymore.

You can build it on Solaris and FreeBSD, for instance, or OS X. Let's now have a look at how our roadmap looks like. What is next for replication? We will continue to build on Group Replication technology, the Group Replication plugin itself, rapid releases, improved performance, stability, and usability. We are also very focused on improving replication usability, instrument more replication, expose more stats, replication stats through Performance Schema tables, add simpler administrative commands, and more online operations. Also, of course, performance is a big thing, continue to work on improving replication performance. Make sure that we interact or interact with all the other components for orchestration, like Fabric and so on, and the MySQL Router. If I had to split through different areas, this is how it would look like.

There's MySQL replication, and in the high availability corners, there's MySQL Group Replication, recoverability, automation of failover, and crash recovery. These are all areas that are very interesting to us. On the performance side, work on the multithreaded applier, address some of the scalability pain points, and then also delve into some high-performance computing optimizations in the replication code. On the ease of use, further instrumentation for exposing stats through Performance Schema tables. Configurability, that's also an area that we need to work on, and simplifying the user interface is also a very big thing. Integration. Integration is also very big, I would say. We have MySQL Fabric Router, modularization, and plugability. I think these are key areas to make replication more usable. Replication is very popular itself, but to make it even more popular and modernization of replication interfaces.

This is also a very big thing for us. Just to sum it up, if I had to make a picture or draw a picture of how will all these components play together, I would probably draw something like this. You have your application interacting with the router, the router interacts with the Fabric for orchestration and sharding, and you have then your highly available groups, for instance, with Group Replication, where your requests are sent to. On top of this, to monitor all of these things together, you can have MEM, or something else if you have already in your infrastructure and so on. Let's just quickly do a quick summary. I presented MySQL 5.7 replication. Lot of new features, huge work put into this release as usual. There are some things I would like to highlight. Semi-sync has gotten better.

We have worked a lot on performance, the slave is now faster. There's less contention around the binary log, and also it's easier to reconfigure replication. There's more online operations for reconfiguring replication. There's also much more flexibility when fitting MySQL replication in your setups, because now we can do multi-source replication in addition to regular replication. I would also like to highlight the fact that we have these lab releases for Group Replication. They're out there for you to try to send us feedback. We have a lot of detailed blogs about MySQL Group Replication. Feel free to engage with comments on those blogs or file bug reports, or just use it and give us or let us know your experience with it. Where to go from here?

You can go to dev.mysql.com and download the packages and install them, play with MySQL, the new version of MySQL 5.7, set up replication, and so on. You can go to labs.mysql.com. We have there the Group Replication plugin. There's a bunch of other stuff there, not exactly related to replication, but still might be interesting. You can go to this link here, dev.mysql.com/doc/#manual, and check our reference manual there for any detail that you might have missed and you want to educate yourself on. You can go to mysqlhighavailability.com and read our blogs, our engineering blogs, and there's a lot of stuff there, a lot of interesting stuff, low-level stuff as well. Feel free to drop a comment or two to engage us and so on. You are very much welcome to just hang around there if you want. I hope you enjoyed.

Thank you very much for attending. It was a really nice hour here with you. I guess the time for questions is open now. Thank you.