├── Dockerfile ├── LICENSE.txt ├── Makefile ├── README.md ├── VERSIONS ├── check-system ├── memsql-entrypoint.sh ├── memsql-shell ├── setup.sh └── simple-benchmark /Dockerfile: -------------------------------------------------------------------------------- 1 | # 2 | # MemSQL Quickstart Dockerfile 3 | # 4 | # https://github.com/memsql/memsql-docker-quickstart 5 | # 6 | 7 | FROM debian:8.6 8 | MAINTAINER Carl Sverre 9 | 10 | RUN apt-get update && \ 11 | apt-get install -y \ 12 | libmysqlclient-dev \ 13 | mysql-client \ 14 | curl \ 15 | jq \ 16 | python-dev \ 17 | python-pip && \ 18 | apt-get clean && \ 19 | rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* 20 | 21 | # install useful python packages 22 | RUN pip install --upgrade pip 23 | RUN pip install memsql ipython psutil 24 | 25 | # configure locale for utf-8 26 | RUN apt-get update && apt-get install -y locales && rm -rf /var/lib/apt/lists/* \ 27 | && localedef -i en_US -c -f UTF-8 -A /usr/share/locale/locale.alias en_US.UTF-8 28 | ENV LANG en_US.utf8 29 | 30 | # set UTC 31 | RUN ln -sf /usr/share/zoneinfo/UTC /etc/localtime 32 | 33 | # setup directories 34 | RUN mkdir /memsql /memsql-ops 35 | 36 | # download and install MemSQL Ops 37 | # then reduce size by symlinking objdir and lib from one install to the other 38 | COPY setup.sh /tmp/setup.sh 39 | COPY VERSIONS /tmp/VERSIONS 40 | RUN /tmp/setup.sh 41 | 42 | # COPY helper scripts 43 | COPY memsql-shell /usr/local/bin/memsql-shell 44 | COPY check-system /usr/local/bin/check-system 45 | COPY simple-benchmark /usr/local/bin/simple-benchmark 46 | 47 | VOLUME ["/memsql"] 48 | 49 | COPY memsql-entrypoint.sh / 50 | 51 | ENTRYPOINT ["/memsql-entrypoint.sh"] 52 | CMD ["memsqld"] 53 | 54 | # expose ports 55 | EXPOSE 3306 56 | EXPOSE 9000 57 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2017 MemSQL (http://www.memsql.com) 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: latest 2 | latest: 3 | docker build -t memsql/quickstart:latest -f Dockerfile . 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This Image has been Deprecated 2 | ============================ 3 | 4 | ### Please use the official Docker image for testing MemSQL: 5 | https://hub.docker.com/r/memsql/cluster-in-a-box/ 6 | 7 | ### And the official Tutorial for running MemSQL with Docker: 8 | https://docs.singlestore.com/latest/guides/deploy-memsql/self-managed/docker/ 9 | 10 | 11 | 12 | 13 | ### Deprecated Example usage 14 | 15 | ``` 16 | # Pull the image 17 | docker pull memsql/quickstart 18 | 19 | 20 | # Verify your machine satisfies our minimum requirements 21 | docker run --rm memsql/quickstart check-system 22 | 23 | 24 | # Spin up a MemSQL cluster on your machine 25 | docker run -d -p 3306:3306 -p 9000:9000 --name=memsql memsql/quickstart 26 | 27 | 28 | # Run a quick benchmark against MemSQL 29 | docker run --rm -it --link=memsql:memsql memsql/quickstart simple-benchmark 30 | 31 | 32 | # Open a MemSQL command line shell 33 | docker run --rm -it --link=memsql:memsql memsql/quickstart memsql-shell 34 | 35 | 36 | # Stop and remove the container 37 | docker stop memsql && docker rm -v memsql 38 | ``` 39 | 40 | ### Recommended system settings 41 | 42 | It is recommended to run MemSQL and MemSQL Ops with a couple of specific system settings. The full set of settings are documented here: https://docs.memsql.com/tutorials/v5.8/installation-best-practices/ 43 | 44 | One option is to set the settings when you run the container. For example you can do something like this to setup the recommended sysctl settings: 45 | 46 | ``` 47 | docker run -d --sysctl net.core.somaxconn=1024 --sysctl vm.min_free_kbytes=2639550 -p 3306:3306 -p 9000:9000 -v memsql:/memsql --name=memsql memsql/quickstart 48 | ``` 49 | 50 | ### Persistent data (using Docker volumes) 51 | 52 | The image is setup to write all data for the MemSQL nodes into the `/memsql` 53 | directory inside the container. This makes it easy to mount all of the 54 | persistent data into a Docker volume. For example, the following command will 55 | start a new MemSQL quickstart container and save the data into a Docker named 56 | volume called `memsql`. 57 | 58 | ``` 59 | docker run -d -p 3306:3306 -p 9000:9000 -v memsql:/memsql --name=memsql memsql/quickstart 60 | ``` 61 | 62 | If you want to mount any directory on the host machine - the directory first 63 | needs to be initialized. You can do this like so: 64 | 65 | ``` 66 | mkdir /host/data 67 | docker run --rm -v $(pwd)/data:/template memsql/quickstart /bin/bash -c 'cp -r /memsql/* /template && chown -R 1000:1000 /template' 68 | ``` 69 | 70 | And then you can mount it into the quickstart container over `/memsql`: 71 | 72 | ``` 73 | docker run -d -p 3306:3306 -p 9000:9000 -v /host/data:/memsql --name=memsql memsql/quickstart 74 | ``` 75 | 76 | ### Custom schema file at start 77 | 78 | If you mount a SQL file to /schema.sql inside the container it will be loaded 79 | when the cluster is started. Example: 80 | 81 | ``` 82 | echo "CREATE DATABASE test;" > schema.sql 83 | docker run -d -v $(PWD)/schema.sql:/schema.sql -p 3306:3306 -p 9000:9000 --name=memsql memsql/quickstart 84 | ``` 85 | 86 | ### Ignore system requirements check 87 | 88 | MemSQL is designed to run on machines with minimum systems requirements. Please read 89 | [this article](https://help.memsql.com/hc/en-us/articles/115001215583-My-hosts-have-less-than-minimum-MemSQL-system-requirements-How-can-I-make-MemSQL-run-on-those-hosts-) 90 | to understand how disabling this check could lead to a less ideal experience. If you 91 | understand the risk you may disable the check by passing in a `IGNORE_MIN_REQUIREMENTS=1` 92 | Docker environment variable: 93 | 94 | ``` 95 | docker run -d -p 3306:3306 -p 9000:9000 --name=memsql -e IGNORE_MIN_REQUIREMENTS=1 memsql/quickstart 96 | ``` 97 | -------------------------------------------------------------------------------- /VERSIONS: -------------------------------------------------------------------------------- 1 | export OPS_VERSION=6.7.1 2 | export MEMSQL_VERSION=7669a637baaad808f22bb0bd5feeafbd9ea2621c 3 | -------------------------------------------------------------------------------- /check-system: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import psutil 4 | import sys 5 | 6 | ONE_MB = 1024 ** 2 7 | 8 | def check_bound_port(port): 9 | with open("/proc/net/tcp") as tcp: 10 | contents = tcp.read() 11 | 12 | # parse the contents of /proc/net/tcp looking for a bound port 13 | lines = contents.split('\n') 14 | 15 | # skip the header line 16 | for line in lines[1:]: 17 | # format is sl, local_address, rem_address, st (state), ... 18 | # we look for a local address whose port (in hex) matches our target 19 | # port and is also in the listening state (0A) 20 | fields = line.split() 21 | 22 | # ignore malformed lines 23 | if len(fields) < 4: 24 | continue 25 | 26 | local_address = fields[1].split(":") 27 | state = fields[3] 28 | if len(local_address) != 2: 29 | continue 30 | 31 | try: 32 | local_port = int(local_address[1], 16) 33 | if local_port == port and state == "0A": 34 | return True 35 | except ValueError: 36 | continue 37 | 38 | return False 39 | 40 | if __name__ == "__main__": 41 | virtual_memory = psutil.virtual_memory() 42 | cpu_count = psutil.cpu_count() 43 | 44 | if cpu_count < 4: 45 | sys.stderr.write("Error: MemSQL requires at least 4 CPU cores available.\n") 46 | sys.stderr.write("See our documentation for help.\n") 47 | sys.stderr.write("http://docs.memsql.com/latest/setup/docker/\n\n") 48 | sys.exit(1) 49 | 50 | if virtual_memory.total < ONE_MB * 3700: 51 | sys.stderr.write("Error: MemSQL requires at least 4 GB of memory to run.\n") 52 | sys.stderr.write("See our documentation for help.\n") 53 | sys.stderr.write("http://docs.memsql.com/latest/setup/docker/\n\n") 54 | sys.exit(1) 55 | 56 | if check_bound_port(3306): 57 | sys.stderr.write("Error: Port 3306 is already taken.\n") 58 | sys.stderr.write("See our documentation for help.\n") 59 | sys.stderr.write("http://docs.memsql.com/latest/setup/docker/\n\n") 60 | sys.exit(1) 61 | 62 | if check_bound_port(9000): 63 | sys.stderr.write("Error: Port 9000 is already taken.\n") 64 | sys.stderr.write("See our documentation for help.\n") 65 | sys.stderr.write("http://docs.memsql.com/latest/setup/docker/\n\n") 66 | sys.exit(1) 67 | 68 | print("System check successful.") 69 | -------------------------------------------------------------------------------- /memsql-entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | if [[ "$1" = "memsqld" ]]; then 5 | memsql-ops start 6 | 7 | #Eliminate Minimum Core Count Requirement 8 | memsql-ops memsql-update-config --all --key minimum_core_count --value 0 9 | 10 | if [[ "$IGNORE_MIN_REQUIREMENTS" = "1" ]]; then 11 | memsql-ops memsql-update-config --all --key minimum_memory_mb --value 0 12 | fi 13 | 14 | memsql-ops memsql-start --all 15 | memsql-ops memsql-list 16 | 17 | # Check for a schema file at /schema.sql and load it 18 | if [[ -e /schema.sql ]]; then 19 | echo "Loading schema from /schema.sql" 20 | cat /schema.sql 21 | memsql < /schema.sql 22 | fi 23 | 24 | # Tail the logs to keep the container alive 25 | exec tail -F /memsql/master/tracelogs/memsql.log /memsql/leaf/tracelogs/memsql.log 26 | else 27 | exec "$@" 28 | fi 29 | -------------------------------------------------------------------------------- /memsql-shell: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MEMSQL_ADDR="${MEMSQL_PORT_3306_TCP_ADDR-127.0.0.1}" 4 | MEMSQL_PORT="${MEMSQL_PORT_3306_TCP_PORT-3306}" 5 | 6 | mysql -u root -h $MEMSQL_ADDR -P $MEMSQL_PORT --batch -e "select 1" >/dev/null 2>&1 7 | if [ $? -eq 0 ]; then 8 | exec mysql -u root -h $MEMSQL_ADDR -P $MEMSQL_PORT --prompt="memsql> " "$@" 9 | else 10 | echo "Failed to find a MemSQL node." 11 | echo "Ensure you are running this command alongside a running MemSQL " 12 | echo "node or with a Docker link to a MemSQL quickstart container." 13 | exit 1 14 | fi 15 | -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | set -x 4 | 5 | # Expects this file to export $OPS_VERSION and $MEMSQL_VERSION 6 | source /tmp/VERSIONS 7 | 8 | VERSION_URL="http://versions.memsql.com/memsql-ops/$OPS_VERSION" 9 | MEMSQL_VOLUME_PATH="/memsql" 10 | OPS_URL=$(curl -s "$VERSION_URL" | jq -r .payload.tar) 11 | 12 | # setup memsql user 13 | groupadd -r memsql --gid 1000 14 | useradd -r -g memsql -s /bin/false --uid 1000 \ 15 | -d /var/lib/memsql-ops -c "MemSQL Service Account" \ 16 | memsql 17 | 18 | # download ops 19 | curl -s $OPS_URL -o /tmp/memsql_ops.tar.gz 20 | 21 | # install ops 22 | mkdir /tmp/memsql-ops 23 | tar -xzf /tmp/memsql_ops.tar.gz -C /tmp/memsql-ops --strip-components 1 24 | /tmp/memsql-ops/install.sh \ 25 | --host 127.0.0.1 \ 26 | --no-cluster \ 27 | --ops-datadir /memsql-ops \ 28 | --memsql-installs-dir /memsql-ops/installs 29 | 30 | DEPLOY_EXTRA_FLAGS= 31 | if [[ $MEMSQL_VERSION != "developer" ]]; then 32 | DEPLOY_EXTRA_FLAGS="--version-hash $MEMSQL_VERSION" 33 | fi 34 | 35 | memsql-ops memsql-deploy --role master --developer-edition $DEPLOY_EXTRA_FLAGS 36 | memsql-ops memsql-deploy --role leaf --developer-edition --port 3307 $DEPLOY_EXTRA_FLAGS 37 | 38 | MASTER_ID=$(memsql-ops memsql-list --memsql-role=master -q) 39 | MASTER_PATH=$(memsql-ops memsql-path $MASTER_ID) 40 | 41 | LEAF_ID=$(memsql-ops memsql-list --memsql-role=leaf -q) 42 | LEAF_PATH=$(memsql-ops memsql-path $LEAF_ID) 43 | 44 | # We need to clear the maximum-memory setting in the leaf's memsql.cnf otherwise 45 | # when we move to another machine with a different amount of memory the memory 46 | # imbalance nag will show up 47 | memsql-ops memsql-update-config --key maximum_memory --delete $LEAF_ID 48 | 49 | # symlink leaf's static directories to master 50 | for tgt in objdir lib; do 51 | rm -rf $LEAF_PATH/$tgt 52 | ln -s $MASTER_PATH/$tgt $LEAF_PATH/$tgt 53 | done 54 | 55 | # setup mutable directories in the volume 56 | function setup_node_dirs { 57 | local node_name=$1 58 | local node_id=$2 59 | local node_path=$3 60 | 61 | # update socket file 62 | memsql-ops memsql-update-config --key "socket" --value $node_path/memsql.sock $node_id 63 | 64 | mkdir -p /memsql/$node_name 65 | 66 | for tgt in data plancache tracelogs; do 67 | # update the volume template 68 | cp -r $node_path/$tgt /memsql/$node_name 69 | 70 | # symlink the dir 71 | rm -rf $node_path/$tgt 72 | ln -s $MEMSQL_VOLUME_PATH/$node_name/$tgt $node_path/$tgt 73 | done 74 | 75 | # clear the plancache 76 | rm -rf /memsql/$node_name/plancache/* 77 | } 78 | 79 | setup_node_dirs master $MASTER_ID $MASTER_PATH 80 | setup_node_dirs leaf $LEAF_ID $LEAF_PATH 81 | 82 | chown -R memsql:memsql /memsql /memsql-ops 83 | 84 | memsql-ops memsql-stop --all 85 | memsql-ops stop 86 | 87 | # cleanup 88 | rm -rf /tmp/* 89 | rm -rf /memsql-ops/data/cache/* 90 | -------------------------------------------------------------------------------- /simple-benchmark: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import os 4 | import sys 5 | import time 6 | import threading 7 | import argparse 8 | 9 | from memsql.common import database 10 | 11 | parser = argparse.ArgumentParser() 12 | 13 | parser.add_argument("--host", default=None, help="The hostname of the MemSQL node to connect to") 14 | parser.add_argument("--port", default=None, type=int, help="The port of the MemSQL node to connect to") 15 | parser.add_argument("--user", default="root", help="The user of the MemSQL node to connect to") 16 | parser.add_argument("--password", default="", help="The password of the MemSQL node to connect to") 17 | 18 | parser.add_argument("--database", default="simple_benchmark", help="The database to use - note: this database should not exist") 19 | 20 | parser.add_argument("--num-workers", type=int, default=10, help="The number of insert threads") 21 | parser.add_argument("--time", type=int, default=30, help="The number of seconds to run the benchmark for") 22 | 23 | options = parser.parse_args() 24 | 25 | HOST = None 26 | PORT = None 27 | 28 | LINK_MEMSQL_ADDR = os.getenv("MEMSQL_PORT_3306_TCP_ADDR", "127.0.0.1") 29 | LINK_MEMSQL_PORT = int(os.getenv("MEMSQL_PORT_3306_TCP_PORT", 3306)) 30 | 31 | TABLE = "tbl" 32 | BATCH_SIZE = 5000 33 | 34 | # Pre-generate the workload query 35 | QUERY_TEXT = "INSERT INTO %s (val) VALUES %s" % (TABLE, ",".join(["(1)"] * BATCH_SIZE)) 36 | 37 | def get_connection(host=None, port=None, db=options.database): 38 | """ Returns a new connection to the database. """ 39 | if host is None: 40 | host = HOST 41 | if port is None: 42 | port = PORT 43 | 44 | return database.connect( 45 | host=host, 46 | port=port, 47 | user=options.user, 48 | password=options.password, 49 | database=db) 50 | 51 | class InsertWorker(threading.Thread): 52 | """ A simple thread which inserts empty rows in a loop. """ 53 | 54 | def __init__(self, stopping): 55 | super(InsertWorker, self).__init__() 56 | self.stopping = stopping 57 | self.daemon = True 58 | self.exception = None 59 | 60 | def run(self): 61 | with get_connection() as conn: 62 | while not self.stopping.is_set(): 63 | conn.execute(QUERY_TEXT) 64 | 65 | def test_connection(): 66 | try: 67 | with get_connection(db="information_schema") as conn: 68 | conn.ping() 69 | except database.MySQLError: 70 | print("Unable to connect to MemSQL with provided connection details.") 71 | print("Please verify that MemSQL is running @ %s:%s" % (HOST, PORT)) 72 | sys.exit(1) 73 | 74 | def setup_test_db(): 75 | """ Create a database and table for this benchmark to use. """ 76 | 77 | with get_connection(db="information_schema") as conn: 78 | print('Creating database %s' % options.database) 79 | 80 | conn.query('CREATE DATABASE %s' % options.database) 81 | conn.query('USE %s' % options.database) 82 | conn.query('CREATE TABLE IF NOT EXISTS %s (id INT AUTO_INCREMENT PRIMARY KEY, val INT)' % TABLE) 83 | 84 | def warmup(): 85 | print('Warming up workload') 86 | with get_connection() as conn: 87 | conn.execute(QUERY_TEXT) 88 | 89 | def run_benchmark(): 90 | """ Run a set of InsertWorkers and record their performance. """ 91 | 92 | stopping = threading.Event() 93 | workers = [ InsertWorker(stopping) for _ in range(options.num_workers) ] 94 | 95 | print('Launching %d workers' % options.num_workers) 96 | print('Workload will take approximately %d seconds.' % options.time) 97 | 98 | [ worker.start() for worker in workers ] 99 | time.sleep(options.time) 100 | 101 | print('Stopping workload') 102 | 103 | stopping.set() 104 | [ worker.join() for worker in workers ] 105 | 106 | with get_connection() as conn: 107 | count = conn.get("SELECT COUNT(*) AS count FROM %s" % TABLE).count 108 | 109 | print("%d rows inserted using %d threads" % (count, options.num_workers)) 110 | print("%.1f rows per second" % (count / float(options.time))) 111 | 112 | def cleanup(): 113 | """ Cleanup the database this benchmark is using. """ 114 | try: 115 | with get_connection() as conn: 116 | conn.query('DROP DATABASE IF EXISTS %s' % options.database) 117 | except database.MySQLError: 118 | pass 119 | 120 | if __name__ == '__main__': 121 | # try using docker link host/port if the user doesn't specify otherwise 122 | if options.host is None and options.port is None: 123 | try: 124 | with get_connection(host=LINK_MEMSQL_ADDR, port=LINK_MEMSQL_PORT, db="information_schema") as conn: 125 | conn.ping() 126 | options.host = LINK_MEMSQL_ADDR 127 | options.port = LINK_MEMSQL_PORT 128 | except database.MySQLError: 129 | pass 130 | 131 | HOST = options.host or "127.0.0.1" 132 | PORT = options.port or 3306 133 | 134 | cleanup() 135 | 136 | try: 137 | test_connection() 138 | setup_test_db() 139 | warmup() 140 | run_benchmark() 141 | except KeyboardInterrupt: 142 | print("Interrupted... exiting...") 143 | --------------------------------------------------------------------------------