タイトル: SQLのログ出力方法
SEOタイトル: MySQL / PostgreSQL / Laravel / Hibernate で SQL ログを出す方法まとめ
| この記事の要点 |
|
MySQL のクエリログ
一般クエリログ(全 SQL 記録)
-- 現在の状態確認
SHOW VARIABLES LIKE 'general_log%';
-- general_log | OFF
-- general_log_file | /var/lib/mysql/host.log
-- 動的に有効化(再起動不要)
SET GLOBAL general_log_file = '/tmp/mysql_query.log';
SET GLOBAL general_log = 'ON';
-- 確認
SELECT * FROM mysql.general_log ORDER BY event_time DESC LIMIT 10;
-- ログ出力先をテーブルに(FILE / TABLE / NONE)
SET GLOBAL log_output = 'TABLE';
-- 無効化
SET GLOBAL general_log = 'OFF';
パフォーマンスに影響するので本番では一時的にのみ使用。
スロークエリログ
-- 状態確認
SHOW VARIABLES LIKE 'slow_query%';
SHOW VARIABLES LIKE 'long_query_time';
-- 1 秒以上かかるクエリを記録
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 1;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
-- インデックス未使用も記録
SET GLOBAL log_queries_not_using_indexes = 'ON';
-- 確認
mysqldumpslow -s t -t 10 /var/log/mysql/slow.log
my.cnf で恒久設定
# /etc/mysql/my.cnf or /etc/my.cnf
[mysqld]
general_log = 1
general_log_file = /var/log/mysql/general.log
slow_query_log = 1
slow_query_log_file = /var/log/mysql/slow.log
long_query_time = 1
log_queries_not_using_indexes = 1
# 再起動が必要
# systemctl restart mysql
PostgreSQL のクエリログ
# postgresql.conf
log_destination = 'stderr'
logging_collector = on
log_directory = 'log'
log_filename = 'postgresql-%Y-%m-%d.log'
# 何をログに出すか
log_statement = 'all' # all / ddl / mod / none
log_min_duration_statement = 1000 # ms。1秒以上のクエリ
# 詳細フォーマット
log_line_prefix = '%t [%p]: user=%u,db=%d,app=%a,client=%h '
log_duration = on # 実行時間も記録
# 反映
# SELECT pg_reload_conf();
セッション単位での有効化
-- セッション中だけ詳細ログ
SET log_statement = 'all';
SET log_min_duration_statement = 0;
-- pg_stat_statements 拡張で集計
CREATE EXTENSION pg_stat_statements;
SELECT query, calls, total_exec_time, mean_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
Laravel での SQL ログ
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
// 方法1: enableQueryLog + getQueryLog
DB::enableQueryLog();
User::where('id', 1)->get();
$queries = DB::getQueryLog();
// [['query' => 'select * from users where id = ?', 'bindings' => [1], 'time' => 1.23]]
// 方法2: DB::listen でリアルタイムログ
DB::listen(function ($query) {
Log::info('[SQL] ' . $query->sql, [
'bindings' => $query->bindings,
'time_ms' => $query->time,
]);
});
// AppServiceProvider::boot() で常時有効化(開発環境のみ)
public function boot(): void
{
if (app()->environment('local')) {
DB::listen(function ($q) {
$sql = vsprintf(str_replace('?', '%s', $q->sql), array_map(
fn($v) => is_string($v) ? "'$v'" : $v,
$q->bindings
));
Log::channel('sql')->info("[{$q->time}ms] $sql");
});
}
}
Telescope / Debugbar 利用
# Laravel Telescope(公式デバッグツール)
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate
# → /telescope で全 SQL 確認可能
# Laravel Debugbar(画面下に表示)
composer require barryvdh/laravel-debugbar --dev
# .env で APP_DEBUG=true なら自動表示
Spring Boot / Hibernate での SQL ログ
# application.yml
spring:
jpa:
show-sql: true # 標準出力に SQL
properties:
hibernate:
format_sql: true # 整形
use_sql_comments: true # JPQL コメント付き
logging:
level:
org.hibernate.SQL: DEBUG # SQL 本体
org.hibernate.orm.jdbc.bind: TRACE # バインドパラメータ (Hibernate 6+)
org.hibernate.type.descriptor.sql.BasicBinder: TRACE # バインド (Hibernate 5)
org.springframework.jdbc.core.JdbcTemplate: DEBUG # Spring JDBC
org.springframework.jdbc.core.StatementCreatorUtils: TRACE # JDBC バインド
P6Spy で更に詳細
p6spy
p6spy
3.9.1
# application.properties
spring.datasource.url=jdbc:p6spy:mysql://localhost:3306/mydb
spring.datasource.driver-class-name=com.p6spy.engine.spy.P6SpyDriver
Node.js (Sequelize / Prisma / TypeORM)
// Sequelize
const sequelize = new Sequelize(uri, {
logging: console.log, // 全 SQL を console に
logging: (sql, time) => logger.debug({ sql, time }),
});
// TypeORM
new DataSource({
type: 'mysql',
logging: ['query', 'error', 'schema'],
logger: 'advanced-console',
});
// Prisma (schema.prisma で datasource 設定後)
const prisma = new PrismaClient({
log: [{ emit: 'event', level: 'query' }],
});
prisma.$on('query', (e) => {
console.log('Query: ' + e.query);
console.log('Duration: ' + e.duration + 'ms');
});
本番環境での注意
- 全クエリログはI/O が増えて性能劣化、本番では一時的に or スロークエリのみ
- 個人情報(メール / パスワードハッシュ)がログに乗る可能性 → アクセス権限管理を厳格に
- ログローテーションを設定(
logrotate等)してディスク満杯を防ぐ - 本番で詳細ログを取るなら pg_stat_statements / performance_schema のような集計型がベター
FAQ
Q: ORM のログでバインド変数が ? のままで実値が見えない
A: フレームワーク別に詳細ログレベルが用意されています(Hibernate: BasicBinder=TRACE、Laravel: DB::listen で bindings を取れる)。
Q: クエリの実行計画も見たい
A: EXPLAIN SELECT ...(MySQL/PostgreSQL)。本番遅延調査には必須です。