{"id":72,"date":"2016-01-26T23:24:41","date_gmt":"2016-01-26T22:24:41","guid":{"rendered":"http:\/\/188.166.119.205\/?p=72"},"modified":"2026-11-10T05:52:02","modified_gmt":"2026-11-10T05:52:02","slug":"mysql-in-docker-or-native-performance-benchmarks","status":"publish","type":"post","link":"https:\/\/banyek.net\/?p=72&lang=en","title":{"rendered":"MySQL in docker or native \u2013 performance benchmarks"},"content":{"rendered":"<p><a href=\"http:\/\/188.166.119.205\/2015\/10\/02\/running-multiple-instances-on-the-same-hardware\/\">Back in October I have write about possible ways of running multiple MySQL instances on the same hardware<\/a>. As the months passing by, the project of splitting our database schemas into standalone instances is closing in, so I started to check the different ways.<\/p>\n<p>EDIT: This post is outdated, <a href=\"http:\/\/188.166.119.205\/2016\/02\/15\/mysql-docker-performance-report-update\/\">here<\/a> is the follow up.<\/p>\n<p><!--more--><\/p>\n<p>I started with docker, because we\u2019ll use containers anyway with the applications, and I think it is a good idea to minimise the diversity of an infrastructure. I used the docker\u2019s \u201cofficial\u201d Percona image (it is official by Docker not by Percona!) which is easy to use, and flexible enough. (https:\/\/hub.docker.com\/_\/percona\/) This image supports using custom config files, you can mount your existing directories (data &amp; log) for the container, it is nice at the first sight. I found only one caveat with this: if I stop the docker container with **docker kill then the mysql server will be crash, so if you want to clean shut down the instance you have to kill the mysql server inside the container with kill, and after it stopped you can remove the container itself.<\/p>\n<pre><code>[root@db-dev.bfc \/home\/banyek\/conf]# docker ps\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\ne791b3728ab5 percona \"\/docker-entrypoint.s\" 3 minutes ago Up 3 minutes 0.0.0.0:3306-&gt;3306\/tcp mysql-dev\n[root@db-dev.bfc \/home\/banyek\/conf]# docker exec e791b3728ab5 killall mysqld\n[root@db-dev.bfc \/home\/banyek\/conf]# docker rm e791b3728ab5\ne791b3728ab5\n<\/code><\/pre>\n<p>My first test was to run our development servers with docker containers instead of native mysql servers which was jolly good. I start the database instance with mounting the current data directory and the binlog directory inside the container, and I use a slightly modified (datafiles &amp; directories) config file inside the container.<\/p>\n<pre><code>[root@db-dev.bfc \/home\/banyek\/conf]# docker run --name mysql-dev -v \/home\/banyek\/conf:\/etc\/mysql\/conf.d -v \/var\/lib\/mysql:\/var\/lib\/mysql -v \/var\/log\/mysql:\/var\/log\/mysql -p 3306:3306 -d percona\n954360158d7a5c2e050b7049c73a8a098b550da6e3d2e336b43bd690e34e9738\n[root@db-dev.bfc \/home\/banyek\/conf]# docker ps\nCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES\n954360158d7a percona \"\/docker-entrypoint.s\" 7 seconds ago Up 6 seconds 0.0.0.0:3306-&gt;3306\/tcp mysql-dev\n[root@db-dev.bfc \/home\/banyek\/conf]# mysql -h 127.0.0.1\nWelcome to the MySQL monitor. Commands end with ; or \\g.\n[...]\npercona@db-dev.bfc.kinja-ops.com (127.0.0.1) [(none)]&gt;\n<\/code><\/pre>\n<p>There\u2019s only one thing you have to worried about: the local connections will come from the <strong>docker0<\/strong> network interface, so you have to add it\u2019s ip address to the allowed hosts list. (Which is 172.17.0.1 at our site.)<\/p>\n<p>This instance can be used from any of the applications it can be a part of the replica chain, etc.<\/p>\n<p>After I used dockerized mysql for a while in the dev environment, I decided to bechmark it with <strong>sysbench<\/strong>.<\/p>\n<p>I recommend using the 0.5 branch (<a href=\"https:\/\/github.com\/akopytov\/sysbench\">which is available on github<\/a>) because the 0.4.12 (the stable one) didn\u2019t supports parallel benchmarking of databases so your results won\u2019t be applicable comparing to a real workload. After compiling sysbench, we can start our tests.<\/p>\n<p>During the tests I created once the \u2018<em>sbtest<\/em>\u2019 database manually (in mysql prompt <em>create database sbtest<\/em>) and after I was populated it with test data with the following command:<\/p>\n<pre><code>.\/sysbench --test=tests\/db\/parallel_prepare.lua --mysql_host=127.0.0.1 --mysql-user=XXX --mysql-password=YYY --oltp-tables-count=64 --num-threads=8 run\n<\/code><\/pre>\n<pre><code>#and the tests were ran with the following command:\n\n.\/sysbench --test=tests\/db\/oltp.lua --mysql_host=127.0.0.1 --mysql-user=XXX --mysql-password=YYY --oltp-tables-count=64 --num-threads=8 --max-time=60 run\n<\/code><\/pre>\n<p>I ran the test 3 times with native mysql and 3 times with the containerised one. I recorded the end results from the 3rd runs only for avoiding the problems which could be caused by cold caches.<\/p>\n<p>Here are the results:<\/p>\n<p>Native MySQL:<\/p>\n<pre><code>Running the test with following options:\nNumber of threads: 8\nRandom number generator seed is 0 and will be ignored\n<\/code><\/pre>\n<pre><code>Threads started!\n<\/code><\/pre>\n<pre><code>OLTP test statistics:\n queries performed:\n read: 140140\n write: 40040\n other: 20020\n total: 200200\n transactions: 10010 (1928.10 per sec.)\n read\/write requests: 180180 (34705.80 per sec.)\n other operations: 20020 (3856.20 per sec.)\n ignored errors: 0 (0.00 per sec.)\n reconnects: 0 (0.00 per sec.)\n<\/code><\/pre>\n<pre><code>General statistics:\n total time: 5.1916s\n total number of events: 10010\n total time taken by event execution: 41.4529s\n response time:\n min: 2.97ms\n avg: 4.14ms\n max: 15.98ms\n approx. 95 percentile: 5.34ms\n<\/code><\/pre>\n<pre><code>Threads fairness:\n events (avg\/stddev): 1251.2500\/43.21\n execution time (avg\/stddev): 5.1816\/0.00\n<\/code><\/pre>\n<p>And here are the results with docker:<\/p>\n<pre><code>Threads started!\n<\/code><\/pre>\n<pre><code>OLTP test statistics:\n queries performed:\n read: 140000\n write: 40000\n other: 20000\n total: 200000\n transactions: 10000 (1127.79 per sec.)\n read\/write requests: 180000 (20300.19 per sec.)\n other operations: 20000 (2255.58 per sec.)\n ignored errors: 0 (0.00 per sec.)\n reconnects: 0 (0.00 per sec.)\n ```\n<\/code><\/pre>\n<p>General statistics:<br \/>\ntotal time: 8.8669s<br \/>\ntotal number of events: 10000<br \/>\ntotal time taken by event execution: 70.8362s<br \/>\nresponse time:<br \/>\nmin: 4.52ms<br \/>\navg: 7.08ms<br \/>\nmax: 22.28ms<br \/>\napprox. 95 percentile: 9.14ms<br \/>\n&#8220;`<\/p>\n<pre><code>Threads fairness:\n events (avg\/stddev): 1250.0000\/60.86\n execution time (avg\/stddev): 8.8545\/0.00\n<\/code><\/pre>\n<p>The results are disappointing. The MySQL server running in a docker instance performs somewhere between 1\/2 and 2\/3 of the native one, which is unacceptable.<\/p>\n<p>I started the container with the following command, so it is possible that we can avoid this performance overhead by mounting the data directory more smart (directly from LVM? With some <em>magic<\/em> mount parameters?) but so far the results are these, and the verdict is \u201cit is not the best idea\u201d.<\/p>\n<pre><code>[root@db-dev.bfc \/home\/banyek]# docker run --name mysql-dev -v \/home\/banyek\/conf:\/etc\/mysql\/conf.d -v \/var\/lib\/mysql:\/var\/lib\/mysql -v \/var\/log\/mysql:\/var\/log\/mysql -p 3306:3306 -d percona\n<\/code><\/pre>\n<p>I\u2019ll check the other options &amp; performance tuning later.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Back in October I have write about possible ways of running multiple MySQL instances on the same hardware. As the months passing by, the project of splitting our database schemas into standalone instances is closing in, so I started to check the different ways. EDIT: This post is outdated, here is the follow up.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[134],"tags":[192,194,144,126,196],"class_list":["post-72","post","type-post","status-publish","format-standard","hentry","category-tech-en","tag-benchmark-en","tag-docker-en","tag-mysql-en","tag-oldblog-en","tag-sysbench-en"],"_links":{"self":[{"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/posts\/72","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/banyek.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=72"}],"version-history":[{"count":1,"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/posts\/72\/revisions"}],"predecessor-version":[{"id":421,"href":"https:\/\/banyek.net\/index.php?rest_route=\/wp\/v2\/posts\/72\/revisions\/421"}],"wp:attachment":[{"href":"https:\/\/banyek.net\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=72"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/banyek.net\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=72"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/banyek.net\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=72"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}