PHP 怎么PHP 数据库追踪

wen PHP项目 2

本文目录导读:

PHP 怎么PHP 数据库追踪

  1. 使用SQL日志记录
  2. PDO扩展监控
  3. 数据库查询分析器
  4. 数据库连接池监控
  5. 使用第三方工具
  6. 完整的追踪中间件示例
  7. 最佳实践建议

我来为您详细介绍PHP数据库追踪的几种实现方法:

使用SQL日志记录

简单SQL查询日志

class DatabaseLogger {
    private $logFile;
    public function __construct($logFile = 'sql_log.txt') {
        $this->logFile = $logFile;
    }
    public function logQuery($sql, $params = [], $executionTime = 0) {
        $logEntry = sprintf(
            "[%s] SQL: %s | Params: %s | Time: %.4fs\n",
            date('Y-m-d H:i:s'),
            $sql,
            json_encode($params),
            $executionTime
        );
        file_put_contents($this->logFile, $logEntry, FILE_APPEND);
    }
}
// 使用示例
$logger = new DatabaseLogger();
$start = microtime(true);
$result = $db->query("SELECT * FROM users WHERE id = ?", [1]);
$executionTime = microtime(true) - $start;
$logger->logQuery("SELECT * FROM users WHERE id = ?", [1], $executionTime);

PDO扩展监控

自定义PDO类实现追踪

class MonitoredPDO extends PDO {
    private $queries = [];
    public function query($query, $fetchMode = null, ...$fetchModeArgs) {
        $start = microtime(true);
        $result = parent::query($query, $fetchMode, ...$fetchModeArgs);
        $executionTime = microtime(true) - $start;
        $this->queries[] = [
            'sql' => $query,
            'time' => $executionTime,
            'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS)
        ];
        return $result;
    }
    public function getQueries() {
        return $this->queries;
    }
    public function getQueryCount() {
        return count($this->queries);
    }
    public function getTotalExecutionTime() {
        return array_sum(array_column($this->queries, 'time'));
    }
}
// 使用示例
$db = new MonitoredPDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$db->query("SELECT * FROM users");
$db->query("INSERT INTO logs SET action='test'");
print_r($db->getQueries());
echo "Total queries: " . $db->getQueryCount();
echo "Total time: " . $db->getTotalExecutionTime();

数据库查询分析器

完整的查询追踪系统

class QueryAnalyzer {
    private $queries = [];
    private $slowQueryThreshold = 1.0; // 1秒
    public function startQuery($sql, $params = []) {
        $queryId = uniqid('query_');
        $this->queries[$queryId] = [
            'sql' => $sql,
            'params' => $params,
            'start_time' => microtime(true),
            'backtrace' => debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5)
        ];
        return $queryId;
    }
    public function endQuery($queryId) {
        if (!isset($this->queries[$queryId])) {
            return;
        }
        $this->queries[$queryId]['end_time'] = microtime(true);
        $this->queries[$queryId]['duration'] = 
            $this->queries[$queryId]['end_time'] - $this->queries[$queryId]['start_time'];
        // 检测慢查询
        if ($this->queries[$queryId]['duration'] > $this->slowQueryThreshold) {
            $this->reportSlowQuery($this->queries[$queryId]);
        }
    }
    private function reportSlowQuery($queryInfo) {
        $message = sprintf(
            "慢查询警告: %.4f秒\nSQL: %s\nParams: %s\n调用栈: %s",
            $queryInfo['duration'],
            $queryInfo['sql'],
            json_encode($queryInfo['params']),
            json_encode($queryInfo['backtrace'])
        );
        error_log($message);
        // 可以发送邮件或记录到专门的慢查询日志
    }
    public function getStatistics() {
        $stats = [
            'total_queries' => count($this->queries),
            'total_time' => 0,
            'avg_time' => 0,
            'slow_queries' => 0,
            'fastest' => PHP_FLOAT_MAX,
            'slowest' => 0
        ];
        foreach ($this->queries as $query) {
            if (isset($query['duration'])) {
                $stats['total_time'] += $query['duration'];
                $stats['fastest'] = min($stats['fastest'], $query['duration']);
                $stats['slowest'] = max($stats['slowest'], $query['duration']);
                if ($query['duration'] > $this->slowQueryThreshold) {
                    $stats['slow_queries']++;
                }
            }
        }
        if ($stats['total_queries'] > 0) {
            $stats['avg_time'] = $stats['total_time'] / $stats['total_queries'];
        }
        return $stats;
    }
}
// 使用示例
$analyzer = new QueryAnalyzer();
$queryId = $analyzer->startQuery("SELECT * FROM users WHERE id = ?", [1]);
// 执行查询...
$analyzer->endQuery($queryId);
print_r($analyzer->getStatistics());

数据库连接池监控

class ConnectionPoolMonitor {
    private $connections = [];
    private $maxConnections = 10;
    public function createConnection($config) {
        if (count($this->connections) >= $this->maxConnections) {
            throw new Exception("达到最大连接数限制");
        }
        $connectionId = uniqid('conn_');
        $this->connections[$connectionId] = [
            'created_at' => microtime(true),
            'config' => $config,
            'queries' => 0,
            'last_activity' => time()
        ];
        return $connectionId;
    }
    public function trackQuery($connectionId) {
        if (isset($this->connections[$connectionId])) {
            $this->connections[$connectionId]['queries']++;
            $this->connections[$connectionId]['last_activity'] = time();
        }
    }
    public function closeConnection($connectionId) {
        if (isset($this->connections[$connectionId])) {
            $info = $this->connections[$connectionId];
            $lifetime = microtime(true) - $info['created_at'];
            // 记录连接使用情况
            error_log(sprintf(
                "连接 %s 关闭: %d 查询, 存活 %.2f 秒",
                $connectionId,
                $info['queries'],
                $lifetime
            ));
            unset($this->connections[$connectionId]);
        }
    }
    public function getStatus() {
        return [
            'active_connections' => count($this->connections),
            'total_queries' => array_sum(array_column($this->connections, 'queries')),
            'max_connections' => $this->maxConnections
        ];
    }
}

使用第三方工具

集成 Xdebug 追踪

// php.ini 配置
/*
xdebug.mode = trace
xdebug.trace_output_dir = /var/log/xdebug
xdebug.trace_options = 1
*/
// 代码中启用
xdebug_start_trace('/var/log/xdebug/app_trace.xt');
// 执行数据库操作...
xdebug_stop_trace();

使用 Query Monitor (WordPress)

// 在WordPress开发环境中使用
if (defined('WP_DEBUG') && WP_DEBUG) {
    // Query Monitor 插件会自动追踪所有SQL查询
    // 并通过工具栏显示
}

完整的追踪中间件示例

class DatabaseTracingMiddleware {
    private $db;
    private $logHandler;
    private $monitor;
    public function __construct($db, $logHandler = null) {
        $this->db = $db;
        $this->logHandler = $logHandler ?: new FileLogger();
        $this->monitor = new PerformanceMonitor();
    }
    public function query($sql, $params = []) {
        $queryId = $this->monitor->startTracking();
        try {
            $start = microtime(true);
            $result = $this->db->query($sql, $params);
            $duration = microtime(true) - $start;
            // 记录查询
            $this->logHandler->log([
                'sql' => $sql,
                'params' => $params,
                'duration' => $duration,
                'memory' => memory_get_usage(),
                'timestamp' => date('Y-m-d H:i:s')
            ]);
            // 追踪性能
            $this->monitor->endTracking($queryId, $duration);
            // 慢查询告警
            if ($duration > 1.0) {
                $this->sendSlowQueryAlert($sql, $duration);
            }
            return $result;
        } catch (Exception $e) {
            $this->logHandler->error([
                'sql' => $sql,
                'params' => $params,
                'error' => $e->getMessage(),
                'timestamp' => date('Y-m-d H:i:s')
            ]);
            throw $e;
        }
    }
    private function sendSlowQueryAlert($sql, $duration) {
        // 发送邮件、Slack通知等
        $message = "慢查询警告: {$sql} " . "耗时: {$duration}秒";
        // 实现具体通知逻辑
    }
}
// 使用
$tracker = new DatabaseTracingMiddleware($db);
$users = $tracker->query("SELECT * FROM users WHERE status = ?", ['active']);

最佳实践建议

  1. 生产环境谨慎使用:过多的日志可能影响性能
  2. 定期清理日志:设置日志轮转策略
  3. 分级监控:开发环境全量记录,生产环境只记录慢查询和错误
  4. 使用索引:确保被追踪的查询使用合适的索引
  5. 异步记录:考虑使用消息队列异步处理日志
  6. 隐私保护:不要在日志中记录敏感数据

这些方法可以根据您的具体需求组合使用,实现对数据库操作的全面追踪和监控。

抱歉,评论功能暂时关闭!