diff --git a/.travis.yml b/.travis.yml
index f1e95f32d..c7b315e86 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,27 +1,31 @@
+sudo: required
 language: ruby
 bundler_args: --without benchmarks
+addons:
+  homebrew:
+    packages:
+      - mysql
 script:
   - bundle exec rake spec
-# Temporary workaround for broken Rubygems on Travis
 before_install:
-  - gem update --system 2.4.8
   - gem --version
   - |
-    bash -c " # Install MySQL 5.7 if DB=mysql57
-    if [[ x$DB =~ mysql57 ]]; then
-      sudo bash .travis_mysql57.sh
+    bash -c " # Install MySQL if DB=mysql*
+    if [[ x$DB =~ xmysql ]]; then
+      sudo bash .travis_mysql.sh '$DB'
     fi
     "
   - |
-    bash -c " # Install MariaDB if DB=mariadb
+    bash -c " # Install MariaDB if DB=mariadb*
     if [[ x$DB =~ xmariadb ]]; then
       sudo bash .travis_mariadb.sh '$DB'
     fi
     "
   - |
-    bash -c " # Install MySQL is OS=darwin
+    bash -c " # Install MySQL if OS=darwin
     if [[ x$OSTYPE =~ ^xdarwin ]]; then
-      brew install mysql
+      # Disable SSL due to missing certs
+      echo ssl = 0 >> /usr/local/etc/my.cnf
       mysql.server start
     fi
     "
@@ -35,29 +39,32 @@ before_install:
   - mysqld --version
   - mysql -u root -e "CREATE DATABASE IF NOT EXISTS test"
   - mysql -u root -e "CREATE USER '$USER'@'localhost'" || true
-os:
-  - linux
+os: linux
+dist: trusty
 rvm:
   - 1.8.7
   - 1.9.3
   - 2.0.0
   - 2.1
   - 2.2
-  - 2.3.1
+  - 2.3
   - ree
 matrix:
+  fast_finish: true
   allow_failures:
-    - env: DB=mysql57
-    - rvm: rbx-2
     - os: osx
+    - rvm: ree
   include:
     - rvm: 2.0.0
       env: DB=mariadb55
     - rvm: 2.0.0
       env: DB=mariadb10
+    - rvm: 2.0.0
+      env: DB=mysql55
     - rvm: 2.0.0
       env: DB=mysql57
-    - rvm: rbx-2
-      env: RBXOPT=-Xgc.honor_start=true
     - rvm: 2.0.0
+      dist: xenial
+      env: DB=mysql8
+    - rvm: 2.3
       os: osx
diff --git a/.travis_mariadb.sh b/.travis_mariadb.sh
index 652804382..172b570f6 100644
--- a/.travis_mariadb.sh
+++ b/.travis_mariadb.sh
@@ -1,14 +1,21 @@
 #!/bin/sh
+set -e
+
+service mysql status && service mysql stop
 
-service mysql stop
 apt-get purge '^mysql*' 'libmysql*'
-apt-get install python-software-properties
+apt-get autoclean
+
+rm -rf /etc/mysql /var/lib/mysql /var/log/mysql
+
 apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0xcbcb082a1bb943db
 
+. /etc/lsb-release
+
 if [[ x$1 = xmariadb55 ]]; then
-  add-apt-repository 'deb http://ftp.osuosl.org/pub/mariadb/repo/5.5/ubuntu precise main'
+  echo "deb http://ftp.osuosl.org/pub/mariadb/repo/5.5/ubuntu $DISTRIB_CODENAME main" >> /etc/apt/sources.list
 elif [[ x$1 = xmariadb10 ]]; then
-  add-apt-repository 'deb http://ftp.osuosl.org/pub/mariadb/repo/10.0/ubuntu precise main'
+  echo "deb http://ftp.osuosl.org/pub/mariadb/repo/10.3/ubuntu $DISTRIB_CODENAME main" >> /etc/apt/sources.list
 fi
 
 apt-get update
diff --git a/.travis_mysql.sh b/.travis_mysql.sh
new file mode 100644
index 000000000..aef13880f
--- /dev/null
+++ b/.travis_mysql.sh
@@ -0,0 +1,27 @@
+#!/bin/sh
+set -e
+
+service mysql status && service mysql stop
+
+apt-get purge '^mysql*' 'libmysql*'
+apt-get autoclean
+
+rm -rf /etc/mysql /var/lib/mysql /var/log/mysql
+
+apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x8C718D3B5072E1F5
+
+. /etc/lsb-release
+
+if [[ x$1 = xmysql56 ]]; then
+  echo "deb http://repo.mysql.com/apt/ubuntu $DISTRIB_CODENAME mysql-5.6" >> /etc/apt/sources.list
+elif [[ x$1 = xmysql57 ]]; then
+  echo "deb http://repo.mysql.com/apt/ubuntu $DISTRIB_CODENAME mysql-5.7" >> /etc/apt/sources.list
+elif [[ x$1 = xmysql8 ]]; then
+  echo "deb http://repo.mysql.com/apt/ubuntu $DISTRIB_CODENAME mysql-8.0" >> /etc/apt/sources.list
+fi
+
+apt-get update
+apt-get -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold -y install mysql-server libmysqlclient-dev
+
+# disable socket auth on mysql-community-server
+mysql -u root -e "USE mysql; UPDATE user SET plugin='mysql_native_password' WHERE User='root'; FLUSH PRIVILEGES;"
diff --git a/.travis_mysql57.sh b/.travis_mysql57.sh
deleted file mode 100644
index a9f87dda8..000000000
--- a/.travis_mysql57.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-service mysql stop
-
-apt-get purge '^mysql*' 'libmysql*'
-apt-get autoclean
-
-rm -rf /var/lib/mysql
-rm -rf /var/log/mysql
-
-apt-get install python-software-properties
-apt-key adv --recv-keys --keyserver hkp://keyserver.ubuntu.com:80 0x8C718D3B5072E1F5
-add-apt-repository 'deb http://repo.mysql.com/apt/ubuntu/ precise mysql-5.7-dmr'
-
-apt-get update
-apt-get -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold -y install mysql-server libmysqlclient-dev
diff --git a/.travis_ssl.sh b/.travis_ssl.sh
index 4a3f52bb2..d120b3b62 100644
--- a/.travis_ssl.sh
+++ b/.travis_ssl.sh
@@ -37,16 +37,16 @@ commonName_default             = ca_name
 " >> ca.cnf
 
 echo "
-commonName_default             = cert_name
+commonName_default             = localhost
 " >> cert.cnf
 
 # Generate a set of certificates
 openssl genrsa -out ca-key.pem 2048
-openssl req -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem -batch -config ca.cnf
-openssl req -newkey rsa:2048 -days 1000 -nodes -keyout pkcs8-server-key.pem -out server-req.pem -batch -config cert.cnf
-openssl x509 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
-openssl req -newkey rsa:2048 -days 1000 -nodes -keyout pkcs8-client-key.pem -out client-req.pem -batch -config cert.cnf
-openssl x509 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
+openssl req -sha1 -new -x509 -nodes -days 1000 -key ca-key.pem -out ca-cert.pem -batch -config ca.cnf
+openssl req -sha1 -newkey rsa:2048 -days 1000 -nodes -keyout pkcs8-server-key.pem -out server-req.pem -batch -config cert.cnf
+openssl x509 -sha1 -req -in server-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out server-cert.pem
+openssl req -sha1 -newkey rsa:2048 -days 1000 -nodes -keyout pkcs8-client-key.pem -out client-req.pem -batch -config cert.cnf
+openssl x509 -sha1 -req -in client-req.pem -days 1000 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 -out client-cert.pem
 
 # Convert format from PKCS#8 to PKCS#1
 openssl rsa -in pkcs8-server-key.pem -out server-key.pem
@@ -61,4 +61,4 @@ ssl-key=/etc/mysql/server-key.pem
 " >> my.cnf
 
 # Wait until the minute moves to ensure that the SSL cert is within its valid range
-ruby -e 'start = Time.now.min; while Time.now.min == start; sleep 2; end'
+# ruby -e 'start = Time.now.min; while Time.now.min == start; sleep 2; end'
diff --git a/ext/mysql2/client.c b/ext/mysql2/client.c
index 5d75304b4..9b0057e66 100644
--- a/ext/mysql2/client.c
+++ b/ext/mysql2/client.c
@@ -794,10 +794,12 @@ static VALUE _mysql_client_options(VALUE self, int opt, VALUE value) {
       retval = &boolval;
       break;
 
+#if defined(MYSQL_SECURE_AUTH)
     case MYSQL_SECURE_AUTH:
       boolval = (value == Qfalse ? 0 : 1);
       retval = &boolval;
       break;
+#endif
 
     case MYSQL_READ_DEFAULT_FILE:
       charval = (const char *)StringValueCStr(value);
@@ -1182,7 +1184,12 @@ static VALUE set_ssl_options(VALUE self, VALUE key, VALUE cert, VALUE ca, VALUE
 }
 
 static VALUE set_secure_auth(VALUE self, VALUE value) {
+/* This option was deprecated in MySQL 5.x and removed in MySQL 8.0 */
+#if defined(MYSQL_SECURE_AUTH)
   return _mysql_client_options(self, MYSQL_SECURE_AUTH, value);
+#else
+  return Qfalse;
+#endif
 }
 
 static VALUE set_read_default_file(VALUE self, VALUE value) {
@@ -1297,6 +1304,10 @@ void init_mysql2_client() {
 #ifdef CLIENT_LONG_PASSWORD
   rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"),
       LONG2NUM(CLIENT_LONG_PASSWORD));
+#else
+  /* HACK because MariaDB 10.2 no longer defines this constant,
+   * but we're using it in our default connection flags. */
+  rb_const_set(cMysql2Client, rb_intern("LONG_PASSWORD"), INT2NUM(0));
 #endif
 
 #ifdef CLIENT_FOUND_ROWS
diff --git a/ext/mysql2/extconf.rb b/ext/mysql2/extconf.rb
index 8590da386..dd254905c 100644
--- a/ext/mysql2/extconf.rb
+++ b/ext/mysql2/extconf.rb
@@ -104,6 +104,12 @@ def asplode lib
   asplode h unless have_header h
 end
 
+mysql_h = [prefix, 'mysql.h'].compact.join('/')
+
+# my_bool is replaced by C99 bool in MySQL 8.0, but we want
+# to retain compatibility with the typedef in earlier MySQLs.
+have_type('my_bool', mysql_h)
+
 # These gcc style flags are also supported by clang and xcode compilers,
 # so we'll use a does-it-work test instead of an is-it-gcc test.
 gcc_flags = ' -Wall -funroll-loops'
diff --git a/ext/mysql2/mysql2_ext.h b/ext/mysql2/mysql2_ext.h
index d6d5fd626..6350c27d9 100644
--- a/ext/mysql2/mysql2_ext.h
+++ b/ext/mysql2/mysql2_ext.h
@@ -1,6 +1,14 @@
 #ifndef MYSQL2_EXT
 #define MYSQL2_EXT
 
+/* MySQL 8.0 replaces my_bool with C99 bool. Earlier versions of MySQL had
+ * a typedef to char. Gem users reported failures on big endian systems when
+ * using C99 bool types with older MySQLs due to mismatched behavior. */
+#ifndef HAVE_TYPE_MY_BOOL
+#include <stdbool.h>
+typedef bool my_bool;
+#endif
+
 /* tell rbx not to use it's caching compat layer
    by doing this we're making a promise to RBX that
    we'll never modify the pointers we get back from RSTRING_PTR */
diff --git a/ext/mysql2/mysql_enc_name_to_ruby.h b/ext/mysql2/mysql_enc_name_to_ruby.h
index dfabeef1f..b50146d36 100644
--- a/ext/mysql2/mysql_enc_name_to_ruby.h
+++ b/ext/mysql2/mysql_enc_name_to_ruby.h
@@ -1,4 +1,4 @@
-/* C code produced by gperf version 3.0.3 */
+/* C code produced by gperf version 3.0.4 */
 /* Command-line: gperf  */
 /* Computed positions: -k'1,3,$' */
 
@@ -30,7 +30,7 @@ error "gperf generated tables don't work with this execution character set. Plea
 #endif
 
 struct mysql2_mysql_enc_name_to_rb_map { const char *name; const char *rb_name; };
-/* maximum key range = 66, duplicates = 0 */
+/* maximum key range = 71, duplicates = 0 */
 
 #ifdef __GNUC__
 __inline
@@ -46,39 +46,39 @@ mysql2_mysql_enc_name_to_rb_hash (str, len)
 {
   static const unsigned char asso_values[] =
     {
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 40,  5,
-       0, 69,  0, 40, 25, 20, 10, 55, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 35,  5,  0,
-      10,  0, 20,  0,  5,  5, 69,  0, 10, 15,
-       0,  0, 69, 69, 25,  5,  5,  0, 69, 30,
-      69,  0, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69, 69, 69, 69, 69,
-      69, 69, 69, 69, 69, 69
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 15,  5,
+       0, 74,  5, 25, 40, 10, 20, 50, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 40,  5,  0,
+      15, 10,  0,  0,  0,  5, 74,  0, 25,  5,
+       0,  5, 74, 74, 20,  5,  5,  0, 74, 45,
+      74,  0, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74, 74, 74, 74, 74,
+      74, 74, 74, 74, 74, 74
     };
   return len + asso_values[(unsigned char)str[2]] + asso_values[(unsigned char)str[0]] + asso_values[(unsigned char)str[len - 1]];
 }
 
 #ifdef __GNUC__
 __inline
-#ifdef __GNUC_STDC_INLINE__
+#if defined __GNUC_STDC_INLINE__ || defined __GNUC_GNU_INLINE__
 __attribute__ ((__gnu_inline__))
 #endif
 #endif
@@ -89,11 +89,11 @@ mysql2_mysql_enc_name_to_rb (str, len)
 {
   enum
     {
-      TOTAL_KEYWORDS = 39,
+      TOTAL_KEYWORDS = 41,
       MIN_WORD_LENGTH = 3,
       MAX_WORD_LENGTH = 8,
       MIN_HASH_VALUE = 3,
-      MAX_HASH_VALUE = 68
+      MAX_HASH_VALUE = 73
     };
 
   static const struct mysql2_mysql_enc_name_to_rb_map wordlist[] =
@@ -101,54 +101,58 @@ mysql2_mysql_enc_name_to_rb (str, len)
       {""}, {""}, {""},
       {"gbk", "GBK"},
       {""},
-      {"greek", "ISO-8859-7"},
+      {"utf32", "UTF-32"},
       {"gb2312", "GB2312"},
       {"keybcs2", NULL},
       {""},
       {"ucs2", "UTF-16BE"},
       {"koi8u", "KOI8-R"},
       {"binary", "ASCII-8BIT"},
-      {"eucjpms", "eucJP-ms"},
-      {""},
+      {"utf8mb4", "UTF-8"},
+      {"macroman", "macRoman"},
       {"ujis", "eucJP-ms"},
-      {"cp852", "CP852"},
+      {"greek", "ISO-8859-7"},
       {"cp1251", "Windows-1251"},
-      {"geostd8", NULL},
+      {"utf16le", "UTF-16LE"},
       {""},
       {"sjis", "Shift_JIS"},
       {"macce", "macCentEuro"},
-      {"latin2", "ISO-8859-2"},
+      {"cp1257", "Windows-1257"},
+      {"eucjpms", "eucJP-ms"},
+      {""},
+      {"utf8", "UTF-8"},
+      {"cp852", "CP852"},
+      {"cp1250", "Windows-1250"},
+      {"gb18030", "GB18030"},
       {""},
-      {"macroman", "macRoman"},
-      {"dec8", NULL},
-      {"utf32", "UTF-32"},
-      {"latin1", "ISO-8859-1"},
-      {"utf8mb4", "UTF-8"},
-      {"hp8", NULL},
       {"swe7", NULL},
+      {"koi8r", "KOI8-R"},
+      {"tis620", "TIS-620"},
+      {"geostd8", NULL},
+      {""},
+      {"big5", "Big5"},
       {"euckr", "EUC-KR"},
-      {"cp1257", "Windows-1257"},
+      {"latin2", "ISO-8859-2"},
       {""}, {""},
-      {"utf8", "UTF-8"},
-      {"koi8r", "KOI8-R"},
-      {"cp1256", "Windows-1256"},
-      {""}, {""}, {""},
-      {"cp866", "IBM866"},
+      {"dec8", NULL},
+      {"cp850", "CP850"},
+      {"latin1", "ISO-8859-1"},
+      {""},
+      {"hp8", NULL},
+      {""},
+      {"utf16", "UTF-16"},
       {"latin7", "ISO-8859-13"},
       {""}, {""}, {""},
       {"ascii", "US-ASCII"},
-      {"hebrew", "ISO-8859-8"},
-      {""}, {""},
-      {"big5", "Big5"},
-      {"utf16", "UTF-16"},
-      {"cp1250", "Windows-1250"},
-      {""}, {""}, {""},
-      {"cp850", "CP850"},
-      {"tis620", "TIS-620"},
+      {"cp1256", "Windows-1256"},
       {""}, {""}, {""},
       {"cp932", "Windows-31J"},
+      {"hebrew", "ISO-8859-8"},
+      {""}, {""}, {""}, {""},
       {"latin5", "ISO-8859-9"},
-      {""}, {""}, {""}, {""}, {""}, {""},
+      {""}, {""}, {""},
+      {"cp866", "IBM866"},
+      {""}, {""}, {""}, {""}, {""}, {""}, {""},
       {"armscii8", NULL}
     };
 
diff --git a/ext/mysql2/mysql_enc_to_ruby.h b/ext/mysql2/mysql_enc_to_ruby.h
index 37dbf6f73..f4c7673c7 100644
--- a/ext/mysql2/mysql_enc_to_ruby.h
+++ b/ext/mysql2/mysql_enc_to_ruby.h
@@ -54,13 +54,13 @@ const char *mysql2_mysql_enc_to_rb[] = {
   "macRoman",
   "UTF-16",
   "UTF-16",
-  NULL,
+  "UTF-16LE",
   "Windows-1256",
   "Windows-1257",
   "Windows-1257",
   "UTF-32",
   "UTF-32",
-  NULL,
+  "UTF-16LE",
   "ASCII-8BIT",
   NULL,
   "US-ASCII",
@@ -74,7 +74,7 @@ const char *mysql2_mysql_enc_to_rb[] = {
   NULL,
   "KOI8-R",
   "KOI8-R",
-  NULL,
+  "UTF-8",
   "ISO-8859-2",
   "ISO-8859-9",
   "ISO-8859-13",
@@ -119,10 +119,10 @@ const char *mysql2_mysql_enc_to_rb[] = {
   "UTF-16",
   "UTF-16",
   "UTF-16",
-  NULL,
-  NULL,
-  NULL,
-  NULL,
+  "UTF-16",
+  "UTF-16",
+  "UTF-16",
+  "UTF-16",
   NULL,
   NULL,
   NULL,
@@ -146,6 +146,10 @@ const char *mysql2_mysql_enc_to_rb[] = {
   "UTF-16BE",
   "UTF-16BE",
   "UTF-16BE",
+  "UTF-16BE",
+  "UTF-16BE",
+  "UTF-16BE",
+  "UTF-16BE",
   NULL,
   NULL,
   NULL,
@@ -153,11 +157,11 @@ const char *mysql2_mysql_enc_to_rb[] = {
   NULL,
   NULL,
   NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
+  "UTF-16BE",
+  "UTF-32",
+  "UTF-32",
+  "UTF-32",
+  "UTF-32",
   "UTF-32",
   "UTF-32",
   "UTF-32",
@@ -186,10 +190,6 @@ const char *mysql2_mysql_enc_to_rb[] = {
   NULL,
   NULL,
   NULL,
-  NULL,
-  NULL,
-  NULL,
-  NULL,
   "UTF-8",
   "UTF-8",
   "UTF-8",
@@ -210,17 +210,70 @@ const char *mysql2_mysql_enc_to_rb[] = {
   "UTF-8",
   "UTF-8",
   "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
   NULL,
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "GB18030",
+  "GB18030",
+  "GB18030",
   NULL,
   NULL,
   NULL,
   NULL,
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
   NULL,
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
   NULL,
   "UTF-8",
   "UTF-8",
@@ -240,6 +293,18 @@ const char *mysql2_mysql_enc_to_rb[] = {
   "UTF-8",
   "UTF-8",
   "UTF-8",
+  NULL,
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  NULL,
+  "UTF-8",
+  NULL,
+  NULL,
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
+  "UTF-8",
   "UTF-8",
   "UTF-8"
 };
diff --git a/ext/mysql2/result.c b/ext/mysql2/result.c
index dcad2f74c..519aff12d 100644
--- a/ext/mysql2/result.c
+++ b/ext/mysql2/result.c
@@ -3,6 +3,7 @@
 #include <stdint.h>
 
 #include "mysql_enc_to_ruby.h"
+#define MYSQL2_CHARSETNR_SIZE (sizeof(mysql2_mysql_enc_to_rb)/sizeof(mysql2_mysql_enc_to_rb[0]))
 
 #ifdef HAVE_RUBY_ENCODING_H
 static rb_encoding *binaryEncoding;
@@ -161,7 +162,7 @@ static VALUE mysql2_set_field_string_encoding(VALUE val, MYSQL_FIELD field, rb_e
     const char *enc_name;
     int enc_index;
 
-    enc_name = mysql2_mysql_enc_to_rb[field.charsetnr-1];
+    enc_name = (field.charsetnr-1 < MYSQL2_CHARSETNR_SIZE) ? mysql2_mysql_enc_to_rb[field.charsetnr-1] : NULL;
     if (enc_name != NULL) {
       /* use the field encoding we were able to match */
       enc_index = rb_enc_find_index(enc_name);
diff --git a/spec/mysql2/client_spec.rb b/spec/mysql2/client_spec.rb
index 5a443b228..303d8bbe9 100644
--- a/spec/mysql2/client_spec.rb
+++ b/spec/mysql2/client_spec.rb
@@ -131,10 +131,10 @@ def connect *args
     ssl_client = nil
     lambda {
       ssl_client = Mysql2::Client.new(
+        :host      => '127.0.0.1', # MySQL 5.7 skips SSL over Unix Sockets w/o ssl-mode=REQUIRED
         :sslkey    => '/etc/mysql/client-key.pem',
         :sslcert   => '/etc/mysql/client-cert.pem',
         :sslca     => '/etc/mysql/ca-cert.pem',
-        :sslcapath => '/etc/mysql/',
         :sslcipher => 'DHE-RSA-AES256-SHA'
       )
     }.should_not raise_error(Mysql2::Error)
@@ -232,7 +232,15 @@ def connect *args
       it "should > 0" do
         # "the statement produces extra information that can be viewed by issuing a SHOW WARNINGS"
         # http://dev.mysql.com/doc/refman/5.0/en/explain-extended.html
-        @client.query("explain extended select 1")
+        begin
+          @client.query("explain extended select 1")
+        rescue Mysql2::Error
+          # EXTENDED keyword is deprecated in MySQL 8.0 and triggers a syntax error
+          # https://dev.mysql.com/doc/refman/5.7/en/explain-extended.html
+          # "extended output is now enabled by default, so the EXTENDED keyword is superfluous and
+          # deprecated ... and it will be removed from EXPLAIN syntax in a future MySQL release"
+          @client.query("explain select 1")
+        end
         @client.warning_count.should > 0
       end
     end
diff --git a/support/mysql_enc_to_ruby.rb b/support/mysql_enc_to_ruby.rb
index 4a3ef70db..00a230851 100644
--- a/support/mysql_enc_to_ruby.rb
+++ b/support/mysql_enc_to_ruby.rb
@@ -42,7 +42,9 @@
   "binary"   => "ASCII-8BIT",
   "geostd8"  => "NULL",
   "cp932"    => "Windows-31J",
-  "eucjpms"  => "eucJP-ms"
+  "eucjpms"  => "eucJP-ms",
+  "utf16le"  => "UTF-16LE",
+  "gb18030"  => "GB18030",
 }
 
 client     = Mysql2::Client.new(:username => user, :password => pass, :host => host, :port => port.to_i)
@@ -67,7 +69,9 @@
 encodings_with_nil = encodings_with_nil.map do |encoding|
   name = "NULL"
 
-  if !encoding.nil? && encoding[1] != "NULL"
+  if !encoding.nil? && encoding[1].nil?
+    $stderr.puts "WARNING: Missing mapping for MySQL collation with id #{encoding[0]}, assuming NULL"
+  elsif !encoding.nil? && encoding[1] != "NULL"
     name = "\"#{encoding[1]}\""
   end
 
diff --git a/support/ruby_enc_to_mysql.rb b/support/ruby_enc_to_mysql.rb
index 112016c94..482613d7a 100644
--- a/support/ruby_enc_to_mysql.rb
+++ b/support/ruby_enc_to_mysql.rb
@@ -37,7 +37,9 @@
   "binary"   => "ASCII-8BIT",
   "geostd8"  => nil,
   "cp932"    => "Windows-31J",
-  "eucjpms"  => "eucJP-ms"
+  "eucjpms"  => "eucJP-ms",
+  "utf16le"  => "UTF-16LE",
+  "gb18030"  => "GB18030",
 }
 
 puts <<-header