MySQLパスワード変更後にPHPアプリが接続できない:114la旧記事の安全な診断ガイド

メンテナンス注記(2026-09-01確認): これは114laの現在のインストール手順やサポート文書ではありません。2011年の短い記事を、MySQLまたはMariaDBを使うPHPアプリケーション向けの認証情報ローテーションと障害切り分けガイドに改訂したものです。古いスナップショットのダウンロードリンクからソフトウェアを入手せず、実際のパスワードをコマンドライン、チケット、公開ログに貼り付けないでください。

パスワード変更後にアプリケーションが「データベースに接続できない」と表示しても、データベースのパスワードが間違っているとは限りません。サーバーアカウント、アプリ設定、ネットワークまたはUnix socket、TLS、PHPドライバーのどの不一致でも似た症状になります。最初に正確な接続タプルとロールバック地点を確定し、一度に一つの変数だけを変更します。

ここでいう「114la」とは

2011-08-03付けの公式サイトのアーカイブは、114啦をオープンソースのウェブディレクトリ/ナビゲーションサイト構築プログラムと説明し、ページをV1.15と表示しています。この背景は旧記事のPHP設定パスとMySQLフィールドに整合します。そのため、この記事では「114la」を当時のPHP/MySQL製ウェブディレクトリアプリケーションと解釈します。

このスナップショットが示すのは、当時そのサイトが自らをどう説明していたかだけです。記事の設定パスが全リリースで使えることや、現在残るダウンロード、ドメイン、配布物が原プロジェクトによって保守され、安全であることは証明しません。今回の確認では、現在保守されている検証可能な公式アップストリームを確認できませんでした。旧スナップショットは来歴の証拠であり、ダウンロード先やサポート窓口ではありません。

まず正しい障害モデルを作る

パスワードを再変更する前に、接続を四つの層に分けます。

  1. データベースアカウント: MySQL/MariaDBのアカウントはユーザー名と接続元ホストの組み合わせです。たとえば、'app_user'@'localhost''app_user'@'10.%'は別アカウントです。
  2. アプリ設定: データベース側のパスワードを変えても、PHPアプリに保存された認証情報は自動更新されません。設定だけを変えてもデータベースアカウントは変わりません。
  3. 転送先: ホスト、ポート、Unix socket、データベース名、TLS設定が実環境と一致する必要があります。Unixでは、localhostがsocketを選び、127.0.0.1が通常TCPを選ぶことがあります。
  4. ランタイム: PHP拡張、認証プラグイン対応、コンテナ/VMネットワーク、プロセス環境、キャッシュされた設定も結果に影響します。

変更前の停止条件

次のいずれかを満たせない場合は、本番で試行錯誤せず停止します。

  • アプリケーションとデータベースアカウントを管理する明示的な権限がない。
  • メンテナンス時間がない、または書き込み処理とキューを停止/排出できない。
  • 最近のバックアップ、事業者スナップショット、または検証済みの復旧経路がない。ファイルが存在するだけでは有効なバックアップとはいえず、復元テストで確認します。方式はサーバーのバージョンとストレージエンジンに合わせます。
  • 元の接続タプルが不明、またはロールバック用の旧認証情報が管理されたパスワードマネージャーにない。
  • アプリがデータベースroot、リモートroot、'user'@'%'、または不要なグローバル権限を使っている。まずDBAに独立した最小権限アカウントを作成してもらいます。障害を権限拡大の理由にしません。
  • データベース製品と正確なバージョンが不明。MySQLとMariaDBのアカウント挙動、認証プラグイン、パスワード変更構文は、すべてのリリースで互換ではありません。

秘密ではなくベースラインを記録する

バージョンはPHPアプリと同じコンテナ、VM、またはホストで取得し、管理者が承認した非公開コンソールにだけ残します。

mysql --version
php --version
php --modules | grep -E '^(mysqli|pdo_mysql)$'

管理された変更記録に正確な接続タプルを残します。ただし、パスワードそのものはコピーせずsecret managerの参照を記録します。

項目正確に確認する内容
データベース製品/バージョンMySQLまたはMariaDB、正確なバージョン
データベースアカウント正確なユーザー名とアカウントの接続元ホスト
エンドポイントホスト名とポート、またはUnix socketパス
データベース正確なデータベース名と文字セット要件
転送リモートか、TLSモード、CA、証明書ホスト名
PHPランタイムPHPバージョン、mysqli/pdo_mysql、実際のコンテナまたはホスト
設定元設定ファイル、サービス環境、コンテナsecret、プラットフォームsecretのうち唯一の正本

パスワードをスクリーンショット、Shellのexport、チャット、チケット、コマンド引数に入れないでください。MySQLは--password=value-pSECRETが安全でないと明記しています。値なしの--passwordまたは-pで対話プロンプトを出すか、承認済みで保護されたログイン方式を使います。

同じランタイム環境から再現する

最初に、アプリと同じ転送方式を選びます。次のTCP例の値はすべてプレースホルダーです。

mysql 
  --protocol=TCP 
  --host='<EXACT_DB_HOST>' 
  --port='<EXACT_DB_PORT>' 
  --user='<LEAST_PRIVILEGE_APP_USER>' 
  --password 
  --database='<EXACT_DB_NAME>' 
  --execute='SELECT CURRENT_USER(), USER(), DATABASE(), @@hostname, @@port, @@version, @@version_comment;'

アプリがUnix socketを使う場合は個別にテストし、ホストとポートを同時に指定しません。

mysql 
  --protocol=SOCKET 
  --socket='<EXACT_SOCKET_PATH>' 
  --user='<LEAST_PRIVILEGE_APP_USER>' 
  --password 
  --database='<EXACT_DB_NAME>' 
  --execute='SELECT CURRENT_USER(), USER(), DATABASE(), @@hostname, @@port, @@version, @@version_comment;'

接続できたら、同じセッションで実際に一致したアカウント、権限、TLS状態を取得します。出力はアクセス制限したメンテナンス記録だけに置きます。

SELECT CURRENT_USER(), USER(), DATABASE(), @@hostname, @@port, @@version, @@version_comment;
SHOW GRANTS;
SHOW STATUS LIKE 'Ssl_cipher';

CURRENT_USER()はサーバーが権限検査に実際に使ったアカウント、USER()はクライアントが提示したIDです。異なる場合は、接続元ホストによるアカウント照合を先に調べます。リモート接続では組織の方針に従う信頼済みCAを使い、対応クライアントではVERIFY_IDENTITYで証明書とホスト名の両方を検証します。接続だけを目的に証明書検証を無効にしません。

一度に一つの限定的なローテーションを行う

変更票は一つのアプリケーションアカウントと一つのデプロイを明示します。

  1. メンテナンスモードに入り、バックグラウンドの書き込み処理を排出します。
  2. SHOW GRANTS、ヘルスベースライン、現在の設定バージョンを保存し、バックアップ/スナップショットと復旧担当者を確認します。
  3. 対象の正確なアカウント'APP_USER'@'EXACT_APP_HOST'を確認します。rootを変更せず、リモートrootも作りません。
  4. 実際の秘密をShell履歴、プロセス一覧、チャットに残さない事業者コンソール、DBAツール、または承認済み経路でランダムなパスワードを生成して設定します。
  5. アプリのパスワード参照だけを更新します。ホスト、ポート、データベース名、認証プラグイン、権限を同時に変えません。
  6. 後述の受け入れ確認を実行します。失敗したら変更を重ねず、文書化したロールバックを使います。

現代のサーバーにおける文の形を以下に示しますが、アカウント境界を明示するためだけの例です。バージョンを確認せず実行してはいけません

ALTER USER '<APP_USER>'@'<EXACT_APP_HOST>'
  IDENTIFIED BY '<NEW_RANDOM_SECRET>';

例の秘密はプレースホルダーです。対話型SQLクライアントでも実値を履歴や監査ログに残す可能性があるため、事業者/DBAが承認したsecret安全なツールを使います。正確なMySQLまたはMariaDBバージョンの文書を先に確認してください。旧版ではDBAから互換手順を得て、検索結果から古いSET PASSWORD、システムテーブル直接更新、FLUSH PRIVILEGESの手順をコピーしません。

MySQL 8.0.14以降では、権限とクライアント互換性を確認した場合に二重パスワードで切替時間を短縮できます。これはMariaDBに共通の構文ではなく、受け入れテストの代わりにもなりません。プレースホルダーを実際の秘密に置き換えてShellやチケットに貼り付けないでください。

ALTER USER '<APP_USER>'@'<EXACT_APP_HOST>'
  IDENTIFIED BY '<NEW_RANDOM_SECRET>'
  RETAIN CURRENT PASSWORD;

ALTER USER '<APP_USER>'@'<EXACT_APP_HOST>'
  DISCARD OLD PASSWORD;

新設定が受け入れ確認を通過し、すべての旧プロセスが終了した後にだけDISCARD OLD PASSWORDを実行します。

アプリ設定は独立して更新する

2011年の記事は/admin/config/cfg_database.phpを挙げていますが、114laの全リリースでそのパスや構造が使われたとする十分な証拠はありません。自分が管理する検証済み環境でのみ設定の正本を特定します。編集前にファイルと権限メタデータをバックアップし、共有端末に内容を出力しません。

アプリが環境変数またはプラットフォームのsecret注入に対応する場合、現代のPHP設定における概念上の対応は次のようになります。

$GLOBALS['database']['db_user'] = getenv('APP_DB_USER');
$GLOBALS['database']['db_pass'] = getenv('APP_DB_PASSWORD');
$GLOBALS['database']['db_name'] = getenv('APP_DB_NAME');
$GLOBALS['database']['db_host'] = getenv('APP_DB_HOST');

これは114laにそのまま適用するパッチではありません。値がないときアプリが安全に失敗し、PHPプロセスが承認済みsecretストアから変数を受け取ることを先に確認します。旧アプリがファイルしか読めない場合は、秘密を漏らさない編集/デプロイ手順で更新します。アーキテクチャ上可能ならWebルート外に置き、必要なサービスアカウントだけに読み取りを許可し、Gitには決してコミットしません。公開可能なディレクトリに.envを置かないでください。

変更したファイルを最初に構文検査します。パスはプレースホルダーです。

php -l '<PATH_TO_CHANGED_PHP_CONFIG>'

その後、設定を実際に読むアプリプロセスだけを再読み込みします。データベース再起動を既定の修復にしません。接続させるためにGRANT ALL ON .を実行したり、接続元を%に広げたり、弱い/非推奨の認証プラグインに切り替えたりしてはいけません。

バージョン、認証プラグイン、TLSのゲート

  • ALTER USERの前にバージョンを確認します。 MySQLとMariaDBでは、リリースごとに対応句と必要権限が異なります。二重パスワードのRETAIN CURRENT PASSWORD/DISCARD OLD PASSWORDは、該当するMySQLバージョンの文書に従ってのみ使います。
  • 認証を弱くする前にクライアントを更新します。 mysql_native_passwordはMySQL 8.0.34で非推奨、8.4で既定無効、9.0で削除済みです。旧PHPドライバーがサーバーの認証方式を扱えない場合は、対応するPHP/MySQLクライアントの組み合わせへの更新を優先します。PHP文書ではcaching_sha2_passwordの完全対応はPHP 7.4.4からですが、実際のビルドとドライバーも検証します。
  • socketとTCPを混同しません。 PDO MySQL DSNでは、Unix socketはhost/portとは別の接続形式です。アプリが実際に使う形式を再現します。
  • リモートTLSを検証します。 必要なTLSモード、CA、証明書ホスト名を維持します。証明書エラーは修正すべき信頼またはホスト名の問題であり、検証を無効にする理由ではありません。

エラー分類ごとに問題を絞る

症状最初に確認してはいけないこと
Access denied for user ...secret参照、user@host照合、アカウントのロック/期限、アプリが旧secretを読んでいないかrootパスワードの反復変更、%への拡大
Unknown database正確なデータベース名、大文字小文字、アカウント権限エラーを隠すため同名の空DBを作る
Connection refused/タイムアウトホスト、ポート、リスナー、コンテナネットワーク、ファイアウォール、サービス状態最初にDBパスワードを変える
No such file or directory(socket)実socketパス、アプリがlocalhostをsocketと解釈するか任意のsocketファイルを作る
非対応の認証方式/プラグインサーバープラグイン、PHPドライバー、バージョン互換性慣習的にmysql_native_passwordを有効化する
TLS/証明書検証失敗CA、証明書チェーン、ホスト名、クライアントTLSモード、時計証明書検証を無効にする
CLIは成功、PHPは失敗PHPの実コンテナ/ユーザー、拡張、設定元、常駐プロセス、デプロイキャッシュDBパスワードを再び変更する

ログには診断に必要な時刻、エラー分類/コード、リクエスト相関IDだけを残します。共有前にパスワード、接続文字列、ホスト、ユーザー名、データベース名、絶対パス、Cookie、トークンを除去します。生の例外ページや設定全体をフォーラムにアップロードしないでください。

受け入れ確認とロールバック

次の限定的な受け入れ手順を順に実行します。

  1. アプリと同じ実行環境から、プロンプト式パスワードで読み取り専用接続を確認します。
  2. アプリに新secretを参照させ、php -lを実行し、必要なPHP/workerプロセスだけを再読み込みします。
  3. 機密データを表示しない読み取り専用ページまたはヘルスエンドポイントを確認します。アプリが許す場合は専用テストレコード一件を作成、読取、更新、削除し、後で消去します。
  4. バックグラウンドジョブ/キューが回復し、新たな認証エラーがなく、SHOW GRANTSが変更前と同じで、リモート接続が想定TLSを使うことを確認します。
  5. 合意した時間だけ観察します。MySQL二重パスワードを使った場合は全旧プロセスの終了後にだけ旧パスワードを破棄します。

失敗したら書き込みを停止し、以前のアプリ設定参照に戻します。データベース側が旧パスワードを受け付けない場合は、権限を持つDBAがsecret安全な経路で正確なアプリケーションアカウントに旧認証情報を戻し、再検証します。単なる認証情報不一致でデータベース全体のバックアップを復元しません。データそのものが変更・消失した場合にだけ、検証済みのデータ復旧手順へ移ります。

メンテナー用チェックリスト

  • [ ] 権限、メンテナンス時間、復旧担当者を確認した。
  • [ ] バックアップ/スナップショットの復元を確認し、旧設定とファイル権限を戻せる。
  • [ ] 正確なuser@host、host/portまたはsocket、DB名、PHP/DBバージョン、TLS要件を記録した。
  • [ ] 独立した最小権限アカウントを使い、リモートroot、%への拡大、グローバルGRANT ALLがない。
  • [ ] パスワードはsecret manager、プロンプト式クライアント、承認済みDBA経路だけを通り、CLI引数、Git、チャット、公開ログにない。
  • [ ] パスワード参照だけを変更し、エンドポイント、権限、認証プラグインを同時に変えていない。
  • [ ] CLI、PHPアプリ、キュー、権限、TLSが受け入れ確認を通り、旧パスワードを予定どおり廃止した。
  • [ ] ログを秘匿化し、一時テストファイル/データを削除した。

参考資料

2011年原文アーカイブ(来歴確認専用)

以下のブロックは、source exportで利用者に見えた本文全体、改行、句読点、入れ子のコードフェンスを保持し、行末空白だけを正規化しています。安全上の狭い置換を三か所行い、過去のデータベースユーザー名、パスワード値、データベース名を明示的なプレースホルダーにしました。未変更の値はsource_export/Gitの来歴にのみ残し、保守ページ、コマンド、ログには入れません。

設定を直接編集してホスティング事業者へ問い合わせるという旧文の指示は、現在の手順としては採用しません。バックアップ、最小権限、secret処理、バージョン、TLS、受け入れ確認、ロールバックのゲートがないためです。

MySQL改密码, 114la无法连接数据库


路径为/admin/config/cfg_database.php 这个文件
 例如:
 $GLOBALS [‘database’] [‘db_user’] = ‘[historical database user redacted]’; 数据库用户名
 $GLOBALS [‘database’] [‘db_pass’] = ‘[historical password value redacted]’; 数据库密码
 $GLOBALS [‘database’] [‘db_name’] = ‘[historical database name redacted]’; 数据库名
 $GLOBALS [‘database’] [‘db_host’] = ‘localhost’; 数据库地址
 可以手动修改。
 咨询下空间商数据库正确信息,按提示填入进去就可以了。

Leave a Reply