Làm thế nào để gỡ lỗi truy vấn cơ sở dữ liệu PDO?


140

Trước khi chuyển sang PDO, tôi đã tạo các truy vấn SQL trong PHP bằng cách nối các chuỗi. Nếu tôi gặp lỗi cú pháp cơ sở dữ liệu, tôi chỉ có thể lặp lại chuỗi truy vấn SQL cuối cùng, tự mình thử nó trên cơ sở dữ liệu và điều chỉnh nó cho đến khi tôi sửa lỗi, sau đó đưa mã đó trở lại mã.

Các câu lệnh PDO đã chuẩn bị nhanh hơn và tốt hơn và an toàn hơn, nhưng có một điều làm tôi khó chịu: Tôi không bao giờ thấy truy vấn cuối cùng khi nó được gửi đến cơ sở dữ liệu. Khi tôi gặp lỗi về cú pháp trong nhật ký Apache hoặc tệp nhật ký tùy chỉnh của mình (tôi ghi nhật ký lỗi trong một catchkhối), tôi không thể thấy truy vấn gây ra chúng.

Có cách nào để nắm bắt toàn bộ truy vấn SQL được gửi bởi PDO đến cơ sở dữ liệu và đăng nhập nó vào một tệp không?


4
được ghi vào một tập tin : /var/log/mysql/*. Các tham số ràng buộc PDO không thể gây ra lỗi cú pháp, vì vậy tất cả những gì bạn cần là truy vấn SQL đã chuẩn bị.
Xeoncross

1
xem mã trong stackoverflow.com/questions/210564/ ' (không có trong câu trả lời được chấp nhận). Không phải là đã có một vài cập nhật được đăng.
Mawg nói rằng phục hồi Monica

1
Một dòng đơn giản thông qua Trình soạn thảo: github.com/panique/pdo-debug
Sliq

2
Câu trả lời của Xeoncross đã giúp tôi. Dưới đây là một bài viết giải thích làm thế nào để bật tính năng này. Nó được mặc định trên rất nhiều cài đặt máy chủ. pontikis.net/blog/how-and-when-to-enable-mysql-logs
mrbinky3000

2
Hãy thử vớivar_dump($pdo_instance->debugDumpParams())
Daniel Petrovaliev

Câu trả lời:


99

Bạn nói điều này :

Tôi không bao giờ thấy truy vấn cuối cùng khi nó được gửi đến cơ sở dữ liệu

Chà, thực ra, khi sử dụng các câu lệnh đã chuẩn bị, không có thứ gọi là " truy vấn cuối cùng " :

  • Đầu tiên, một tuyên bố được gửi đến DB và được chuẩn bị ở đó
    • Cơ sở dữ liệu phân tích cú pháp truy vấn và xây dựng một biểu diễn bên trong của nó
  • Và, khi bạn liên kết các biến và thực hiện câu lệnh, chỉ các biến được gửi đến cơ sở dữ liệu
    • Và cơ sở dữ liệu "tiêm" các giá trị vào biểu diễn bên trong của câu lệnh


Để trả lời câu hỏi của bạn :

Có cách nào để nắm bắt toàn bộ truy vấn SQL được gửi bởi PDO đến cơ sở dữ liệu và đăng nhập nó vào một tệp không?

Không: vì không có " truy vấn SQL hoàn chỉnh " ở bất cứ đâu, nên không có cách nào để nắm bắt nó.


Điều tốt nhất bạn có thể làm, cho mục đích gỡ lỗi, là "xây dựng lại" một truy vấn SQL "thực", bằng cách đưa các giá trị vào chuỗi SQL của câu lệnh.

Những gì tôi thường làm, trong loại tình huống này, là:

  • lặp lại mã SQL tương ứng với câu lệnh, với giữ chỗ
  • và sử dụng var_dump (hoặc tương đương) ngay sau đó, để hiển thị các giá trị của các tham số
  • Điều này thường đủ để thấy một lỗi có thể xảy ra, ngay cả khi bạn không có bất kỳ truy vấn "thực" nào mà bạn có thể thực hiện.

Điều này không phải là tuyệt vời, khi nói đến việc gỡ lỗi - nhưng đó là giá của các tuyên bố đã chuẩn bị và những lợi thế mà chúng mang lại.


1
Giải thích tuyệt vời - cảm ơn. Rõ ràng tôi chỉ có những ý tưởng mờ nhạt về cách thức hoạt động của nó. Tôi cho rằng khi câu lệnh được chuẩn bị, đối tượng kết quả chứa một hàm băm hoặc ID số có thể được gửi trở lại cơ sở dữ liệu với các tham số để cắm vào.
Nathan Long

Không có gì :-) ;;; Tôi không biết làm thế nào điều này được thực hiện chi tiết, nhưng tôi cho rằng nó giống như thế - dù sao thì kết quả cũng chính xác như vậy ;;; đó là một trong những điều tốt đẹp với các câu lệnh được chuẩn bị: nếu bạn phải thực hiện cùng một truy vấn nhiều lần, nó sẽ chỉ được gửi đến DB và được chuẩn bị một lần: cho mỗi lần thực hiện, chỉ có dữ liệu sẽ được gửi.
Pascal MARTIN

1
Cập nhật: Aaron Patterson đã đề cập tại Railsconf 2011 rằng anh ta đã thêm các tuyên bố đã chuẩn bị vào Rails, nhưng lợi ích của PostgreQuery nặng hơn nhiều so với MySQL. Ông nói rằng điều này là do MySQL không thực sự tạo ra kế hoạch truy vấn cho đến khi bạn thực hiện truy vấn đã chuẩn bị.
Nathan Long

85

Tìm trong nhật ký cơ sở dữ liệu

Mặc dù Pascal MARTIN đúng nhưng PDO không gửi toàn bộ truy vấn đến cơ sở dữ liệu cùng một lúc, ryeguy đề xuất của sử dụng chức năng ghi nhật ký của DB thực sự cho phép tôi xem truy vấn hoàn chỉnh như được lắp ráp và thực thi bởi cơ sở dữ liệu.

Dưới đây là cách thực hiện: (Những hướng dẫn này dành cho MySQL trên máy Windows - số dặm của bạn có thể thay đổi)

  • Trong my.ini, bên dưới [mysqld]phần, thêm một loglệnh, nhưlog="C:\Program Files\MySQL\MySQL Server 5.1\data\mysql.log"
  • Khởi động lại MySQL.
  • Nó sẽ bắt đầu đăng nhập mọi truy vấn trong tập tin đó.

Tập tin đó sẽ phát triển nhanh chóng, vì vậy hãy chắc chắn xóa nó và tắt ghi nhật ký khi bạn hoàn tất kiểm tra.


1
Chỉ cần một lưu ý - tôi đã phải thoát khỏi dấu gạch chéo trong my.ini. Vì vậy, mục nhập của tôi trông giống như log = "C: \\ temp \\ MySQL \\ mysql.log".
Jim

4
Điều này có thể làm việc tùy thuộc vào các thiết lập của PDO::ATTR_EMULATE_PREPARES. Xem câu trả lời này để biết thêm thông tin: stackoverflow.com/questions/10658865/#answer-10658929
webbiedave

23
Tôi ghét PDO vì điều này.
Salman

1
@webbiedave - oh, wow! Câu trả lời được liên kết của bạn ngụ ý rằng câu trả lời của tôi chỉ hoạt động khi PDO không hoạt động tối ưu, mà gửi toàn bộ truy vấn để tương thích ngược với phiên bản cũ của MySQL hoặc trình điều khiển cũ. Hấp dẫn.
Nathan Long

13
Trong MySQL 5.5+ bạn cần general_logthay vì log. Xem dev.mysql.com/doc/refman/5.5/en/query-log.html
Adrian Macneil

17

Chắc chắn bạn có thể gỡ lỗi bằng chế độ này {{ PDO::ATTR_ERRMODE }} Chỉ cần thêm dòng mới trước truy vấn của bạn, sau đó bạn sẽ hiển thị các dòng gỡ lỗi.

$db->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING );
$db->query('SELECT *******');  

Bạn sẽ không được gọi ->querykhi sử dụng báo cáo chuẩn bị mặc dù?
EoghanM

17

Có lẽ những gì bạn muốn làm là sử dụng debugDumpParams () trên xử lý câu lệnh. Bạn có thể chạy bất cứ lúc nào sau khi ràng buộc các giá trị với truy vấn đã chuẩn bị (không cầnexecute() câu lệnh).

Nó không xây dựng câu lệnh chuẩn bị cho bạn, nhưng nó sẽ hiển thị các tham số của bạn.


2
Vấn đề duy nhất là nó xuất ra bản sửa lỗi thay vì lưu trữ bên trong mà không 'Echoing'. Tôi không thể đăng nhập theo cách này.
Ricardo Martins

3
Bạn có thể sử dụng bộ đệm đầu ra (ob_start () ...) để lưu trữ đầu ra và ghi nhật ký.
Cranio

bug.php.net/orms.php?id=52384 đã sửa trong 7.1, bạn có thể thấy các giá trị :) hơi trễ nhưng đó là php
Sander Visser

12

Một bài viết cũ nhưng có lẽ ai đó sẽ thấy điều này hữu ích;

function pdo_sql_debug($sql,$placeholders){
    foreach($placeholders as $k => $v){
        $sql = preg_replace('/:'.$k.'/',"'".$v."'",$sql);
    }
    return $sql;
}

1
Đối với một chức năng tương tự cũng có thể xử lý các tham số số, hãy xem câu trả lời của tôi (nhờ một người bình luận trên php.net).
Matt Browne

9

Đây là một chức năng để xem SQL hiệu quả sẽ như thế nào, được đánh dấu từ một nhận xét của "Mark" tại php.net :

function sql_debug($sql_string, array $params = null) {
    if (!empty($params)) {
        $indexed = $params == array_values($params);
        foreach($params as $k=>$v) {
            if (is_object($v)) {
                if ($v instanceof \DateTime) $v = $v->format('Y-m-d H:i:s');
                else continue;
            }
            elseif (is_string($v)) $v="'$v'";
            elseif ($v === null) $v='NULL';
            elseif (is_array($v)) $v = implode(',', $v);

            if ($indexed) {
                $sql_string = preg_replace('/\?/', $v, $sql_string, 1);
            }
            else {
                if ($k[0] != ':') $k = ':'.$k; //add leading colon if it was left out
                $sql_string = str_replace($k,$v,$sql_string);
            }
        }
    }
    return $sql_string;
}

Tại sao "Mark" sử dụng dấu hai chấm trước $ k in str_replace(":$k" ....? Các chỉ mục kết hợp đã có nó trong mảng $ params.
Alan

Câu hỏi hay ... điều này có thể giải thích nó: stackoverflow.com/questions/9778887/ . Cá nhân tôi đã sử dụng chức năng này để gỡ lỗi các truy vấn của Doctrine và tôi nghĩ rằng Doctrine sử dụng các tham số được đánh số thay vì được đặt tên nên tôi không nhận thấy vấn đề này. Tôi đã cập nhật chức năng để nó sẽ hoạt động dù có hoặc không có dấu hai chấm hàng đầu.
Matt Browne

lưu ý rằng giải pháp này thay thế :name_longbằng :name. Ít nhất nếu :nameđến trước :name_long. Các câu lệnh được chuẩn bị bởi MySQL có thể xử lý việc này một cách chính xác, vì vậy đừng để điều đó làm bạn bối rối.
Zim84

8

Các truy vấn PDO không được chuẩn bị về phía khách hàng. PDO chỉ cần gửi truy vấn SQL và các tham số đến máy chủ cơ sở dữ liệu. Cơ sở dữ liệu là những gì thay thế (của ?'s). Bạn có hai lựa chọn:

  • Sử dụng chức năng ghi nhật ký DB của bạn (nhưng ngay cả khi đó nó thường được hiển thị dưới dạng hai câu lệnh riêng biệt (nghĩa là "không phải là cuối cùng") ít nhất là với Postgres)
  • Xuất truy vấn SQL và các tham số và tự ghép chúng lại với nhau

Tôi chưa bao giờ nghĩ sẽ kiểm tra nhật ký của DB. Tôi đang tìm kiếm trong thư mục MySQL và không thấy bất kỳ tệp nhật ký nào, nhưng có lẽ đăng nhập là một tùy chọn tôi phải bật ở đâu đó.
Nathan Long

Vâng, bạn phải bật nó lên. Tôi không biết chi tiết cụ thể nhưng theo mặc định, nó không ghi lại mọi truy vấn.
ryeguy

5

hầu như không có gì được nói về hiển thị lỗi ngoại trừ kiểm tra nhật ký lỗi, nhưng có một chức năng khá hữu ích:

<?php
/* Provoke an error -- bogus SQL syntax */
$stmt = $dbh->prepare('bogus sql');
if (!$stmt) {
    echo "\PDO::errorInfo():\n";
    print_r($dbh->errorInfo());
}
?>

( liên kết nguồn )

Rõ ràng là mã này có thể được sửa đổi để được sử dụng như một thông báo ngoại lệ hoặc bất kỳ loại xử lý lỗi nào khác


2
Đây là cách sai. PDO đủ thông minh để làm cho mã này trở nên vô dụng. Chỉ cần nói với nó để ném ngoại lệ về lỗi. PHP sẽ làm phần còn lại, cách tốt hơn chức năng giới hạn này. Ngoài ra, xin vui lòng , học cách không in tất cả các lỗi trực tiếp vào trình duyệt. Có nhiều cách tốt hơn.
Ý thức chung của bạn

3
đó là tài liệu chính thức và tất nhiên không ai sẽ in lỗi đó trong sản xuất, một lần nữa đây là một ví dụ từ trang web chính thức (php.net), xem liên kết bên dưới ví dụ mã. Và chắc chắn tốt hơn nhiều là sử dụng các thông số bổ sung $ db-> setAttribution (PDO :: ATTR_ERRMODE, PDO :: ERRMODE_EXCEPTION) trong phần khởi tạo PDO nhưng tiếc là bạn không thể truy cập vào mã đó
Zippp

4

ví dụ bạn có câu lệnh pdo này:

$query="insert into tblTest (field1, field2, field3)
values (:val1, :val2, :val3)";
$res=$db->prepare($query);
$res->execute(array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
));

bây giờ bạn có thể nhận được truy vấn đã thực hiện bằng cách xác định một mảng như thế này:

$assoc=array(
  ':val1'=>$val1,
  ':val2'=>$val2,
  ':val3'=>$val3,
);
$exQuery=str_replace(array_keys($assoc), array_values($assoc), $query);
echo $exQuery;

1
Đã làm cho tôi. Bạn có lỗi trong mẫu mã thứ hai: ));nên );(chỉ một dấu ngoặc tròn).
Jasom Dotnet

2

Tìm kiếm trên internet tôi thấy đây là một giải pháp chấp nhận được. Một lớp khác được sử dụng thay cho các hàm PDO và PDO được gọi thông qua các lệnh gọi hàm ma thuật. Tôi không chắc chắn điều này tạo ra vấn đề hiệu suất nghiêm trọng. Nhưng nó có thể được sử dụng cho đến khi một tính năng ghi nhật ký hợp lý được thêm vào PDO.

Vì vậy, theo chủ đề này , bạn có thể viết một trình bao bọc cho kết nối PDO của bạn có thể ghi nhật ký và ném ngoại lệ khi bạn gặp lỗi.

Đây là ví dụ đơn giản:

class LoggedPDOSTatement extends PDOStatement    {

function execute ($array)    {
    parent::execute ($array);
    $errors = parent::errorInfo();
    if ($errors[0] != '00000'):
        throw new Exception ($errors[2]);
    endif;
  }

}

vì vậy bạn có thể sử dụng lớp đó thay vì PDOStatement:

$this->db->setAttribute (PDO::ATTR_STATEMENT_CLASS, array ('LoggedPDOStatement', array()));

Dưới đây là một triển khai trang trí PDO được đề cập:

class LoggedPDOStatement    {

function __construct ($stmt)    {
    $this->stmt = $stmt;
}

function execute ($params = null)    {
    $result = $this->stmt->execute ($params); 
    if ($this->stmt->errorCode() != PDO::ERR_NONE):
        $errors = $this->stmt->errorInfo();
        $this->paint ($errors[2]);
    endif;
    return $result;
}

function bindValue ($key, $value)    {
    $this->values[$key] = $value;    
    return $this->stmt->bindValue ($key, $value);
}

function paint ($message = false)    {
    echo '<pre>';
    echo '<table cellpadding="5px">';
    echo '<tr><td colspan="2">Message: ' . $message . '</td></tr>';
    echo '<tr><td colspan="2">Query: ' . $this->stmt->queryString . '</td></tr>';
    if (count ($this->values) > 0):
    foreach ($this->values as $key => $value):
    echo '<tr><th align="left" style="background-color: #ccc;">' . $key . '</th><td>' . $value . '</td></tr>';
    endforeach;
    endif;
    echo '</table>';
    echo '</pre>';
}

function __call ($method, $params)    {
    return call_user_func_array (array ($this->stmt, $method), $params); 
}

}

2

Để đăng nhập MySQL trong WAMP , bạn sẽ cần chỉnh sửa my.ini (ví dụ: dưới wamp \ bin \ mysql \ mysql5.6.17 \ my.ini)

và thêm vào [mysqld]:

general_log = 1
general_log_file="c:\\tmp\\mysql.log"

1

Đây là một hàm tôi đã thực hiện để trả về một truy vấn SQL có tham số "đã giải quyết".

function paramToString($query, $parameters) {
    if(!empty($parameters)) {
        foreach($parameters as $key => $value) {
            preg_match('/(\?(?!=))/i', $query, $match, PREG_OFFSET_CAPTURE);
            $query = substr_replace($query, $value, $match[0][1], 1);
        }
    }
    return $query;
    $query = "SELECT email FROM table WHERE id = ? AND username = ?";
    $values = [1, 'Super'];

    echo paramToString($query, $values);

Giả sử bạn thực hiện như thế này

$values = array(1, 'SomeUsername');
$smth->execute($values);

Hàm này KHÔNG thêm dấu ngoặc kép vào các truy vấn nhưng thực hiện công việc cho tôi.


0

Vấn đề tôi gặp phải với giải pháp bắt các miễn trừ PDO cho mục đích gỡ lỗi là nó chỉ bắt được các miễn trừ PDO (duh), nhưng không bắt được các lỗi cú pháp đã được đăng ký là lỗi php (Tôi không chắc tại sao lại như vậy, nhưng " tại sao "không liên quan đến giải pháp). Tất cả các cuộc gọi PDO của tôi đến từ một lớp mô hình bảng duy nhất mà tôi đã mở rộng cho tất cả các tương tác của mình với tất cả các bảng ... điều này phức tạp khi tôi đang cố gắng gỡ lỗi mã, vì lỗi sẽ đăng ký dòng mã php nơi cuộc gọi thực thi của tôi là được gọi, nhưng không cho tôi biết cuộc gọi thực sự được thực hiện từ đâu. Tôi đã sử dụng đoạn mã sau để giải quyết vấn đề này:

/**
 * Executes a line of sql with PDO.
 * 
 * @param string $sql
 * @param array $params
 */
class TableModel{
    var $_db; //PDO connection
    var $_query; //PDO query

    function execute($sql, $params) { 
        //we're saving this as a global, so it's available to the error handler
        global $_tm;
        //setting these so they're available to the error handler as well
        $this->_sql = $sql;
        $this->_paramArray = $params;            

        $this->_db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->_query = $this->_db->prepare($sql);

        try {
            //set a custom error handler for pdo to catch any php errors
            set_error_handler('pdoErrorHandler');

            //save the table model object to make it available to the pdoErrorHandler
            $_tm = $this;
            $this->_query->execute($params);

            //now we restore the normal error handler
            restore_error_handler();
        } catch (Exception $ex) {
            pdoErrorHandler();
            return false;
        }            
    }
}

Vì vậy, đoạn mã trên bắt được các ngoại lệ BÓNG PDO VÀ lỗi cú pháp php và xử lý chúng theo cùng một cách. Trình xử lý lỗi của tôi trông giống như thế này:

function pdoErrorHandler() {
    //get all the stuff that we set in the table model
    global $_tm;
    $sql = $_tm->_sql;
    $params = $_tm->_params;
    $query = $tm->_query;

    $message = 'PDO error: ' . $sql . ' (' . implode(', ', $params) . ") \n";

    //get trace info, so we can know where the sql call originated from
    ob_start();
    debug_backtrace(); //I have a custom method here that parses debug backtrace, but this will work as well
    $trace = ob_get_clean();

    //log the error in a civilized manner
    error_log($message);

    if(admin(){
        //print error to screen based on your environment, logged in credentials, etc.
        print_r($message);
    }
}

Nếu bất cứ ai có ý tưởng tốt hơn về cách nhận thông tin liên quan đến trình xử lý lỗi của tôi hơn là đặt mô hình bảng làm biến toàn cục, tôi sẽ rất vui khi nghe và chỉnh sửa mã của mình.


0

mã này hoạt động rất tốt cho tôi:

echo str_replace(array_keys($data), array_values($data), $query->queryString);

Đừng quên thay thế dữ liệu $ và $ truy vấn bằng tên của bạn


0

tôi sử dụng lớp này để gỡ lỗi PDO (với Log4PHP )

<?php

/**
 * Extends PDO and logs all queries that are executed and how long
 * they take, including queries issued via prepared statements
 */
class LoggedPDO extends PDO
{

    public static $log = array();

    public function __construct($dsn, $username = null, $password = null, $options = null)
    {
        parent::__construct($dsn, $username, $password, $options);
    }

    public function query($query)
    {
        $result = parent::query($query);
        return $result;
    }

    /**
     * @return LoggedPDOStatement
     */
    public function prepare($statement, $options = NULL)
    {
        if (!$options) {
            $options = array();
        }
        return new \LoggedPDOStatement(parent::prepare($statement, $options));
    }
}

/**
 * PDOStatement decorator that logs when a PDOStatement is
 * executed, and the time it took to run
 * @see LoggedPDO
 */
class LoggedPDOStatement
{

    /**
     * The PDOStatement we decorate
     */
    private $statement;
    protected $_debugValues = null;

    public function __construct(PDOStatement $statement)
    {
        $this->statement = $statement;
    }

    public function getLogger()
    {
        return \Logger::getLogger('PDO sql');
    }

    /**
     * When execute is called record the time it takes and
     * then log the query
     * @return PDO result set
     */
    public function execute(array $params = array())
    {
        $start = microtime(true);
        if (empty($params)) {
            $result = $this->statement->execute();
        } else {
            foreach ($params as $key => $value) {
                $this->_debugValues[$key] = $value;
            }
            $result = $this->statement->execute($params);
        }

        $this->getLogger()->debug($this->_debugQuery());

        $time = microtime(true) - $start;
        $ar = (int) $this->statement->rowCount();
        $this->getLogger()->debug('Affected rows: ' . $ar . ' Query took: ' . round($time * 1000, 3) . ' ms');
        return $result;
    }

    public function bindValue($parameter, $value, $data_type = false)
    {
        $this->_debugValues[$parameter] = $value;
        return $this->statement->bindValue($parameter, $value, $data_type);
    }

    public function _debugQuery($replaced = true)
    {
        $q = $this->statement->queryString;

        if (!$replaced) {
            return $q;
        }

        return preg_replace_callback('/:([0-9a-z_]+)/i', array($this, '_debugReplace'), $q);
    }

    protected function _debugReplace($m)
    {
        $v = $this->_debugValues[$m[0]];

        if ($v === null) {
            return "NULL";
        }
        if (!is_numeric($v)) {
            $v = str_replace("'", "''", $v);
        }

        return "'" . $v . "'";
    }

    /**
     * Other than execute pass all other calls to the PDOStatement object
     * @param string $function_name
     * @param array $parameters arguments
     */
    public function __call($function_name, $parameters)
    {
        return call_user_func_array(array($this->statement, $function_name), $parameters);
    }
}

0

Tôi đã tạo một dự án / kho lưu trữ được soạn nhạc hiện đại cho chính xác điều này tại đây:

gỡ lỗi

Tìm nhà GitHub của dự án tại đây , xem một bài đăng blog giải thích về nó ở đây . Một dòng để thêm vào composer.json của bạn và sau đó bạn có thể sử dụng nó như thế này:

echo debugPDO($sql, $parameters);

$ sql là câu lệnh SQL thô, $ tham số là một mảng các tham số của bạn: Khóa là tên giữ chỗ (": user_id") hoặc số của tham số không tên ("?"), giá trị là .. tốt, giá trị.

Logic đằng sau: Tập lệnh này sẽ đơn giản phân loại các tham số và thay thế chúng thành chuỗi SQL được cung cấp. Siêu đơn giản, nhưng siêu hiệu quả cho 99% trường hợp sử dụng của bạn. Lưu ý: Đây chỉ là một mô phỏng cơ bản, không phải là gỡ lỗi PDO thực sự (vì điều này là không thể vì PHP gửi SQL thô và các tham số đến máy chủ MySQL tách biệt).

Một lời cảm ơn lớn để bigwebguyMike từ sợi StackOverflow Bắt chuỗi truy vấn SQL liệu từ PDO để viết về cơ bản toàn bộ chức năng chính đằng sau kịch bản này. Lớn lên!


0

Cách gỡ lỗi các truy vấn cơ sở dữ liệu mysO PDO trong Ubuntu

TL; DR Ghi nhật ký tất cả các truy vấn của bạn và theo dõi nhật ký mysql.

Các hướng dẫn này dành cho cài đặt Ubuntu 14.04 của tôi. Phát hành lệnh lsb_release -ađể có được phiên bản của bạn. Cài đặt của bạn có thể khác.

Bật đăng nhập vào mysql

  1. Chuyển đến dòng cmd máy chủ dev của bạn
  2. Thay đổi thư mục cd /etc/mysql. Bạn sẽ thấy một tập tin gọi làmy.cnf . Đó là tập tin chúng ta sẽ thay đổi.
  3. Xác nhận bạn đang ở đúng nơi bằng cách gõ cat my.cnf | grep general_log. Điều này lọc các my.cnftập tin cho bạn. Bạn sẽ thấy hai mục: #general_log_file = /var/log/mysql/mysql.log&& #general_log = 1.
  4. Bỏ ghi chú hai dòng đó và lưu thông qua trình soạn thảo bạn chọn.
  5. Khởi động lại mysql : sudo service mysql restart.
  6. Bạn cũng có thể cần phải khởi động lại máy chủ web của mình. (Tôi không thể nhớ lại trình tự tôi đã sử dụng). Đối với cài đặt của tôi, đó là nginx : sudo service nginx restart.

Công việc tốt đẹp! Bạn đã sẵn sàng. Bây giờ, tất cả những gì bạn phải làm là theo đuôi tệp nhật ký để bạn có thể thấy các truy vấn PDO mà ứng dụng của bạn thực hiện trong thời gian thực.

Đuôi nhật ký để xem các truy vấn của bạn

Nhập cmd này tail -f /var/log/mysql/mysql.log.

Đầu ra của bạn sẽ trông giống như thế này:

73 Connect  xyz@localhost on your_db
73 Query    SET NAMES utf8mb4
74 Connect  xyz@localhost on your_db
75 Connect  xyz@localhost on your_db
74 Quit 
75 Prepare  SELECT email FROM customer WHERE email=? LIMIT ?
75 Execute  SELECT email FROM customer WHERE email='a@b.co' LIMIT 5
75 Close stmt   
75 Quit 
73 Quit 

Bất kỳ truy vấn mới nào mà ứng dụng của bạn thực hiện sẽ tự động bật vào xem , miễn là bạn tiếp tục theo dõi nhật ký. Để thoát khỏi đuôi, nhấncmd/ctrl c .

Ghi chú

  1. Cẩn thận: tệp nhật ký này có thể nhận được rất lớn. Tôi chỉ chạy cái này trên máy chủ dev của tôi.
  2. Đăng nhập tập tin nhận được quá lớn? Cắt ngắn nó. Điều đó có nghĩa là tập tin ở lại, nhưng nội dung bị xóa. truncate --size 0 mysql.log.
  3. Thật tuyệt khi tệp nhật ký liệt kê các kết nối mysql. Tôi biết một trong số đó là từ mã mysqli cũ mà tôi đang chuyển đổi. Thứ ba là từ kết nối PDO mới của tôi. Tuy nhiên, không chắc chắn thứ hai đến từ đâu. Nếu bạn biết một cách nhanh chóng để tìm thấy nó, hãy cho tôi biết.

Tín dụng và cảm ơn

Tiếng hét lớn cho câu trả lời của Nathan Long ở trên để người truyền cảm hứng tìm ra điều này trên Ubuntu. Ngoài ra với dikirill cho nhận xét của mình về bài đăng của Nathan dẫn tôi đến giải pháp này.

Yêu bạn stackoverflow!


0

Trong môi trường Debian NGINX tôi đã làm như sau.

Goto /etc/mysql/mysql.conf.dchỉnh sửa mysqld.cnfnếu bạn tìm thấy log-error = /var/log/mysql/error.logthêm 2 dòng dưới đây.

general_log_file        = /var/log/mysql/mysql.log
general_log             = 1

Để xem nhật ký goto /var/log/mysqltail -f mysql.log

Hãy nhớ bình luận những dòng này sau khi bạn hoàn thành việc gỡ lỗi nếu bạn đang xóa môi trường sản xuất mysql.logvì tệp nhật ký này sẽ phát triển nhanh chóng và có thể rất lớn.


không phải ai cũng sử dụng mysql.
Dấu chấm phẩy đáng sợ
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.