MySQL 8.0.21 Compile/Install HOWTO

19 Aug 2020

Don't take this blog post as the One True Way to install MySQL. I am far more familiar with custom-compiling PostgreSQL than I am MySQL. But there's nothing like installing a database from source to learn what a vanilla installation actually looks like!

Create the mysql user and group.

Please note that the mysql user will already exist if you had previously installed MySQL on your system. Note we do this as root:

$ su -
# addgroup --gid 1002 mysql
# adduser --home /home/mysql --uid 1002 --gid 1002 --disabled-password mysql

Install prerequisites

To compile, MySQL requires a few packages to be installed. This list of build packages is cribbed from my PostgreSQL install notes. Note we are doing everything as root:

# apt install \
    build-essential \
    flex \
    bison \
    libreadline6-dev \
    zlib1g-dev \
    libossp-uuid-dev \
    uuid \
    cmake \
    libssl-dev \
    openssl

Get the PostgreSQL source code

This can be found at www.postgresql.org. Note we are doing everything as root:

# cd /usr/local/src
# wget https://github.com/mysql/mysql-server/archive/mysql-8.0.21.tar.gz
# tar -xzvf mysql-8.0.21.tar.gz
# cd mysql-server-mysql-8.0.21
# mkdir bld
# cd bld

Create the following wrapper script for cmake. It just makes life easier:

# vim runcmake.sh

This just helps document what configuration settings you used when you ran CMake. All the available CMake settings are available at https://dev.mysql.com/doc/refman/8.0/en/source-configuration-options.html. The contents of runcmake.sh are:

#!/bin/bash

set -e
set -u
set -o pipefail

cmake \
    .. \
    -DCMAKE_INSTALL_PREFIX=/usr/local/mysql-8.0.21 \
    -DDOWNLOAD_BOOST=1 \
    -DWITH_BOOST=/usr/local/lib/boost

Make and install MySQL:

# chmod +x runcmake.sh
# ./runcmake.sh
# make
# make install

Make a place for the database files:

# cd /usr/local/mysql-8.0.21
# mkdir data
# chown mysql:mysql data
# chmod 750 data
# ./bin/mysqld --initialize --user=mysql
# ./bin/mysql_ssl_rsa_setup
# bin/mysqld_safe --user=mysql &

Log on and change the root password. # ./bin/mysql -u root -p mysql> alter user 'root'@'localhost' identified by 'whatever-password-you-pick';

Make a systemd MySQL control script. Note that we have not explicitly configured MySQL to play nicely with systemd (and there is a MySQL CMake setting to do so) but this systemd file works fine.

# cd /etc/systemd/system
# vim mysql8021.service
[Unit]
Description=MySQL 8.0.21
# This unit can only run after the network is up and running
# (that is, the network target has run)
After=network.target
After=syslog.target

[Service]
# MySQL is a traditional UNIX daemon that forks a child,
# and the initial process exits
Type=forking
# Wait 120 seconds on startup and shutdown to consider the process
# correctly started up or shut down.
TimeoutSec=120
# The UNIX user and group to execute MySQL as
User=mysql
Group=mysql

# If StandardOutput= or StandardError= are set to syslog, journal or kmsg,
# prefix log lines with "mysql"
SyslogIdentifier=mysql

# Let systemd know where MySQL keeps its pid file
PIDFile=/usr/local/mysql-8.0.21/data/mwood-ThinkPad-T460.pid

# Command used to start PostgreSQL
ExecStart= /usr/local/mysql-8.0.21/support-files/mysql.server start
# Command used to reload PostgreSQL
ExecReload=/usr/local/mysql-8.0.21/support-files/mysql.server reload
# Command used to stop PostgreSQL
ExecStop=  /usr/local/mysql-8.0.21/support-files/mysql.server stop

# Use the lowest allowable setting for the OOM killer; this should
# actually disable the OOM killer for MySQL
OOMScoreAdjust=-1000

[Install]
# This unit is part of target multi-user
WantedBy=multi-user.target
# systemctl daemon-reload
# systemctl enable mysql8021

Now start MySQL:

# systemctl start mysql8021

Make a database (optional):

$ /usr/local/mysql-8.0.21/bin/mysql -u root -p
root@localhost:mysql.sock/(none)> create database foo;
root@localhost:mysql.sock/(none)> exit;

Create a user that can do anything in that database (optional):

$ /usr/local/mysql-8.0.21/bin/mysql -u root -p
root@localhost:mysql.sock/(none)> create user 'foo'@'localhost' identified by 'whatever password you choose';
root@localhost:mysql.sock/(none)> grant all privileges on foo.* to 'foo'@'localhost';
root@localhost:mysql.sock/(none)> exit;

You can now log on to your new database with your new user and check that the character set and collation are correct:

$ /usr/local/mysql-8.0.21/bin/mysql -u foo -p foo
foo@localhost:mysql.sock/foo> select @@character_set_database, @@collation_database;
+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| utf8mb4                  | utf8mb4_0900_ai_ci   |
+--------------------------+----------------------+
1 row in set (0.00 sec)