◀ 3.

MySQLへの接続|接続先・認証・TLSとエラーの確認

▶

MySQLへ接続する前に決めること

このページはMySQLサーバーへクライアント接続する入口です。接続後の既定DB選択はデータベースへの接続(USE)、対象の確認はDB一覧へ進んでください。rootの利用やアカウント作成は接続確認の前提ではありません。

サーバー接続、同一接続でのDB選択、権限による一覧の違い

接続先・認証・既定DBを別々に確認する

MySQL8.4のCLIで、管理者から渡されたホスト名・ポート・既存アカウント・信頼済みCA・証明書と一致するサーバー名を使います。Unix系のlocalhostは通常ソケットを選ぶため、TCPのポート確認では--protocol=TCPを明示します。ソケットパスは環境固有であり、常に同じ場所/最速とは限りません。

遠隔接続の形はmysql --protocol=TCP --host=db.example.invalid --port=3306 --user=reader --password --ssl-mode=VERIFY_IDENTITY --ssl-ca=/path/to/ca.pemです。ホスト/利用者/CAは説明用の置換箇所で、そのまま成功するコマンドではありません。パスワードは対話入力し、秘密値を引数・URL・ソースや公開ログへ書きません。証明書やクライアントの対応が不明なら管理者へ確認し、TLSを無効化して接続を通しません。

接続後の読取確認は次です。出力の接続元/アカウント名は診断用で、全文をサイトや質問欄へ公開しません。USER()は提示した利用者と接続元、CURRENT_USER()は通常の直接照会で照合されたアカウントです。stored programの実行文脈とは分けて読みます。

SELECT VERSION() AS server_version, DATABASE() AS default_database,
       USER() AS presented_identity, CURRENT_USER() AS matched_account,
       CONNECTION_ID() AS connection_id;
SHOW SESSION STATUS LIKE 'Ssl_cipher';

TLSで何を確かめたか

MySQL8.4のCLIモード意味
REQUIRED暗号化必須。CA/サーバー名の検証を含まない
VERIFY_CA暗号化とCA検証。サーバー名の一致は別
VERIFY_IDENTITYCAに加え接続名と証明書の一致も検証。不一致なら失敗

検体MySQL8.4.13の自動生成証明書では、同じCAを用いたVERIFY_CAが成功しても、127.0.0.1との名前一致を要求するVERIFY_IDENTITYは失敗しました。これは検証を弱める推奨ではなく「暗号化できた」と「期待した相手を検証できた」を分ける例です。Ssl_cipherが空でないことだけでも、CA/名前の検証成功までは証明しません。

MariaDBのクライアントは別に確認します。MariaDB11.4以降のZero-Configuration SSLは対応するserver/clientと認証plugin等に条件があり、MySQLの--ssl-modeをそのまま共通指定にしません。検体のMariaDB11.8.9 clientではこのMySQLオプションを受け付けませんでした。connector/各言語の既定値もCLIと同一とは限りません。

接続失敗時に変更せず確認する順番

  1. どのクライアント/版から、どのホスト・ポート・transportへ接続したかを確認する。
  2. 到達性、TLS/証明書、認証、初期DBの順にエラーコードと必要な項目だけ確認する。TCP到達はDB認証成功ではない。
  3. 接続できても期待するDB/アカウント/接続IDかを確認する。初期DBへの権限不足とパスワード不一致を同一視しない。
  4. 権限追加・認証plugin変更・公開ポート/FW変更・bind-address変更・サーバー再起動は接続確認と分け、必要性を管理者が判断する。

SSHトンネルは別経路であり、踏み台からDBまでの保護やDB側の認証/TLSを自動保証しません。TLSの名前検証とローカル転送先名の整合も確認します。Dockerのホスト/コンテナ/DNSとネットワークは別物で、host networkや新しいDB/volumeの作成を接続テストの定型にしません。

言語別の旧接続例を読む前に

既存のPDO/Python/JDBC/Node例を以下に保持しますが、全driverでDSN形式が同じという意味ではありません。Node例にはfsのimportとpool終了処理が省略され、URIの秘密値/固定パスワード、DB由来文字列のHTML出力、例外全文の記録にも注意が必要です。利用側に応じた資格情報管理・出力escape・接続解放とTLS設定を個別に調べます。今回の実行検証は各言語の全接続例を動かした保証ではありません。

既存の接続・一覧資料(製品別の補足)

この記事の要点
  • CLI: mysql -h host -P 3306 -u user -p dbname(パスワードはプロンプトで入力)
  • Unixソケットの場所/利用条件とTCPを区別。常に同じ場所/最速とは限らない
  • MySQL CLIのREQUIREDは暗号化必須。CA/名前を検証するモードは別に選ぶ
  • 言語別: PDO/JDBCの接続文字列とPython/Nodeの引数設定は異なる。各driverのTLS/秘密値管理も照合
  • Dockerの接続先はホスト/別コンテナとOS/ネットワーク構成を分ける。host networkを自動追加しない

1. CLI から接続(mysql コマンド)

旧例の注意:root/平文引数/固定password/ソケット最速や設定上書きの実行推奨ではありません。既存の安全なcredential供給を使い、~/.my.cnfを上書きしません。chmodだけでsecretの全保護は完了しません。

# 最小: ローカルの自分アカウント
mysql -u root -p
# Enter password: ********

# host / port / DB 指定
mysql -h 192.168.1.100 -P 3306 -u app -p appdb

# パスワードを直接渡す(履歴に残るので非推奨)
mysql -u root -ppassword

# Unix ソケット指定(速い)
mysql --socket=/var/run/mysqld/mysqld.sock -u root -p

# 設定ファイルに保存(推奨)
cat > ~/.my.cnf <<'EOF'
[client]
host = 127.0.0.1
port = 3306
user = app
password = AppPass!
database = appdb
EOF
chmod 600 ~/.my.cnf
mysql  # 引数不要で接続

2. 接続のオプション

オプション意味
-h, --host接続先ホスト
-P, --portポート(デフォルト 3306)
-u, --userユーザー名
-p, --passwordパスワード(プロンプト推奨)
-D, --database初期 DB(位置引数でも可)
--socketUnix ソケットパス
--protocoltcp / socket / pipe / memory
--ssl-modeDISABLED/PREFERRED/REQUIRED/VERIFY_CA/VERIFY_IDENTITY
--ssl-caCA 証明書
--default-character-setutf8mb4 推奨
-eSQL を実行して終了

3. SSL/TLS で安全に接続

旧例の注意:REQUIREDとCA/名前の検証は別です。shellコマンドとSQLが混在するため一括実行せず、ALTER USERによる本番認証変更を接続確認へ追加しません。

# 強制 SSL
mysql -h prod.example.com -u app -p \
    --ssl-mode=REQUIRED

# CA 検証付き
mysql -h prod.example.com -u app -p \
    --ssl-mode=VERIFY_CA \
    --ssl-ca=/etc/mysql/ca.pem

# サーバ側で SSL 必須化
ALTER USER 'app'@'%' REQUIRE SSL;

-- 状態確認
SHOW STATUS LIKE 'Ssl_cipher';
-- Ssl_cipher | TLS_AES_256_GCM_SHA384

4. PHP PDO で接続

旧例の注意:PDO固有の例です。固定password/例外全文記録やDB値のHTMLへの未escape出力を転用しません。CAオプションだけで全driverの同じ検証を保証しません。

$dsn = 'mysql:host=127.0.0.1;port=3306;dbname=appdb;charset=utf8mb4';
$user = 'app';
$pass = 'AppPass!';

$options = [
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
    PDO::ATTR_EMULATE_PREPARES   => false,
    PDO::MYSQL_ATTR_SSL_CA       => '/etc/mysql/ca.pem',
];

try {
    $pdo = new PDO($dsn, $user, $pass, $options);
} catch (PDOException $e) {
    error_log($e->getMessage());
    http_response_code(500);
    exit('DB connection error');
}

// プリペアドステートメント(必ず使う)
$stmt = $pdo->prepare('SELECT id, name FROM users WHERE active = ?');
$stmt->execute([1]);
foreach ($stmt as $row) {
    echo $row['name'] . "\n";
}

5. Python(pymysql / mysql-connector)

旧例の注意:PyMySQLとSQLAlchemyの設定は別です。URI/固定passwordを共有せず、TLSの検証条件と依存/版を個別に確認します。

import pymysql

conn = pymysql.connect(
    host='127.0.0.1',
    port=3306,
    user='app',
    password='AppPass!',
    database='appdb',
    charset='utf8mb4',
    cursorclass=pymysql.cursors.DictCursor,
    ssl={'ca': '/etc/mysql/ca.pem'},
)

try:
    with conn.cursor() as cur:
        cur.execute('SELECT id, name FROM users WHERE active = %s', (1,))
        for row in cur.fetchall():
            print(row)
finally:
    conn.close()

# SQLAlchemy の場合
# engine = create_engine('mysql+pymysql://app:AppPass!@127.0.0.1/appdb?charset=utf8mb4')

6. Java JDBC

旧例の注意:JDBCのuseSSLだけで相手のCA/名前を検証したと扱いません。Connector/Jの対象版とsslMode等を確認し、秘密値をソースへ残しません。

import java.sql.*;

String url = "jdbc:mysql://127.0.0.1:3306/appdb"
           + "?useSSL=true&serverTimezone=Asia/Tokyo"
           + "&characterEncoding=utf8&useUnicode=true";

try (Connection conn = DriverManager.getConnection(url, "app", "AppPass!");
     PreparedStatement ps = conn.prepareStatement(
         "SELECT id, name FROM users WHERE active = ?")) {
    ps.setInt(1, 1);
    try (ResultSet rs = ps.executeQuery()) {
        while (rs.next()) {
            System.out.println(rs.getInt("id") + " " + rs.getString("name"));
        }
    }
}

7. Node.js(mysql2)

旧例の注意:mysql2の例にはfsのimportとpool終了が省略されています。固定passwordを使わず、TLS/例外/接続解放を対象環境で補ってから利用します。

import mysql from 'mysql2/promise';

const pool = mysql.createPool({
  host: '127.0.0.1',
  port: 3306,
  user: 'app',
  password: 'AppPass!',
  database: 'appdb',
  waitForConnections: true,
  connectionLimit: 10,
  ssl: { ca: fs.readFileSync('/etc/mysql/ca.pem') },
});

const [rows] = await pool.execute(
  'SELECT id, name FROM users WHERE active = ?',
  [1]
);
console.log(rows);

8. Docker コンテナから接続

旧例の注意:Dockerのネットワーク/認証を新規作成する実行例です。接続診断だけのために既存network/DB/volumeを変更せず、rootの平文passwordも転用しません。

# Docker for Mac / Windows: ホストの MySQL に接続
mysql -h host.docker.internal -P 3306 -u root -p

# Linux で同等のことをするなら --add-host
docker run --add-host=host.docker.internal:host-gateway \
    -it mysql:8 mysql -h host.docker.internal -u root -p

# 別コンテナの MySQL に接続(同一ネットワーク)
docker network create app-net
docker run -d --name db --network app-net \
    -e MYSQL_ROOT_PASSWORD=pass mysql:8
docker run -it --rm --network app-net mysql:8 \
    mysql -h db -u root -ppass

9. SSH トンネル経由で接続

旧例の注意:転送経路/転送先名・TLS名前検証の整合と踏み台からDBまでの区間も確認します。実SSH接続や既存転送を検証のために変更していません。

# ローカル 13306 → リモート踏み台 → DB サーバの 3306
ssh -L 13306:db.internal.example.com:3306 -N bastion.example.com

# 別ターミナルから
mysql -h 127.0.0.1 -P 13306 -u app -p appdb

接続エラー早見表

エラー確認 / 対処
ERROR 2003 Can't connect to MySQL server on hostFW / port / bind-address。nc -zv host 3306 で疎通確認
ERROR 2002 Can't connect to local MySQL server through socketサービス停止 or ソケットパス違い。systemctl status mysqld
ERROR 1045 Access deniedパスワード / ユーザー / Host 不一致
ERROR 1130 Host is not allowedユーザーが 'app'@'%' 等を許可していない
SSL connection errorCA 証明書 / 期限 / サーバ証明書 SAN を確認
Public Key Retrieval is not allowedJDBCの認証方式/信頼するサーバー鍵・検証付きTLSを確認。公開鍵取得を無条件で許可しない

FAQ

Q: ローカルから接続できるが、別ホストからは ERROR 1130
A: 接続先/照合アカウント/接続元/TLSとエラーコードを確認します。1130だけで原因を単一に決めず、%のアカウント作成/認証変更を定型対処にしません。

Q: bind-address を 0.0.0.0 にしても外から繋がらない
A: ① FW(iptables / firewalld / Security Group)、② skip-networking 設定、③ netstat -tlnp | grep 3306 で LISTEN 確認。

Q: パスワードに記号を含めると CLI で接続できない
A: シェルの特殊文字エスケープ問題。-p でプロンプトに任せるか、~/.my.cnf 経由で渡す。

元の書式付きコマンド

元例の注意:元のローカル/リモート例です。myname/hostname/mydbは置換箇所。--password=mypassを本番へ転用せず、対話入力と接続先/TLSを確認します。

mysql -u myname -p

元例の注意:元のローカル/リモート例です。myname/hostname/mydbは置換箇所。--password=mypassを本番へ転用せず、対話入力と接続先/TLSを確認します。

mysql --host=hostname --user=myname --password=mypass mydb

検証範囲と一次資料

新規の小規模MySQL8.4.13/MariaDB11.8.9検体の同一接続/別接続、限定権限と各製品の同梱CLIで検証した範囲です。全言語driver/GUI/接続pool/実SSH経路/各OSの導入や証明書運用・PG/Oracle/SQL Serverの旧例の実行成功を保証しません。本番のschema/認証/設定を変更していません。

子ページ

子ページはありません

同階層のページ
  1. MySQLの起動(Windows)
  2. MySQLの起動、停止、再起動(Linux)
  3. MYSQL への接続
  4. データベース一覧の表示
  5. データベースへの接続
  6. テーブル一覧を表示
  7. テーブル定義を確認
  8. ユーザーおよびパスワード一覧の確認

最近更新/作成されたページ