Laravel API 的 mysql 查询未在 performance_schema.events_statements_summary_by_digest 中被跟踪

Posted

技术标签:

【中文标题】Laravel API 的 mysql 查询未在 performance_schema.events_statements_summary_by_digest 中被跟踪【英文标题】:Laravel API's mysql queries not getting tracked in performance_schema.events_statements_summary_by_digest 【发布时间】:2018-09-17 18:09:36 【问题描述】:

我在这里遇到了一些非常奇怪的问题。我们在 AWS EC2 上托管了一个 laravel API,我们使用 RDS(mysql 5.6)。我最近在 RDS 上启用了 performance_schema。以下是我注意到的行为

    我们的 RDS 实例上有两个数据库。一个用于 wordpress,一个用于我们的 laravel API。 Wordpress 数据库查询正在被很好地消化。但是从我们的 laravel 应用程序运行的查询不是。 由于某种原因,当我将 MySql Workbench 连接到 RDS 实例并在我们的 Laravel 数据库上执行查询时,它们会出现在语句摘要中。 我登录了我的 EC2 机器,连接到 RDS 上的 MySQL 并执行了一些查询,它们在语句摘要中得到跟踪。

所以看起来只有从我们的 Laravel 应用程序执行查询时,它们才不会被跟踪。

我们的 Laravel 版本是 4.2。我正在尝试找出过去两天的原因,任何帮助都会让人松一口气。

我在上述所有步骤中使用的用户都是相同的,并且拥有所有数据库的所有权限。

--编辑--

我进行了许多其他测试,他们都指出只有一个结论,即它与 Laravel 有关。我在托管 laravel 的同一台服务器上创建了一个简单的 php 文件。在这个文件中,我使用相同的用户/密码连接到相同的实例/数据库。我在这个文件中唯一做的就是像这样在 $pdo 上运行一个非常简单的查询。

$stmt = $pdo->query('SELECT name FROM trades');
        while ($row = $stmt->fetch())
        
            echo $row['name'] . "\n";
        

它出现在查询分析中 [https://prnt.sc/j3ochd](我也手动检查了 performance_schema.events_statements_summary_by_digest)

然后我可以点击我们的 laravel api,它实际上从交易表本身返回条目(非常类似于我上面运行的查询)。但这会出现在我的查询分析报告(Percona PMM)或 events_statements_summary_by_digest

【问题讨论】:

【参考方案1】:

您必须在数据库中传递options 参数> 连接设置为PDO::ATTR_EMULATE_PREPARES => true

配置 > 数据库.php

'connections' => [

    'mysql' => [
        'driver' => 'mysql',
        'host' => env('DB_HOST', '127.0.0.1'),
        'port' => env('DB_PORT', '3306'),
        'database' => env('DB_DATABASE', 'forge'),
        'username' => env('DB_USERNAME', 'forge'),
        'password' => env('DB_PASSWORD', ''),
        'unix_socket' => env('DB_SOCKET', ''),
        'charset' => 'utf8mb4',
        'collation' => 'utf8mb4_unicode_ci',
        'prefix' => '',
        'strict' => false,
        'engine' => null,
        'options' => [
            PDO::ATTR_EMULATE_PREPARES => true
        ]
    ],

]

默认情况下,laravel 将此选项标记为 PDO::ATTR_EMULATE_PREPARES => false 以提高查询性能。

这里是关于它的快速详细信息。

PDO::ATTR_EMULATE_PREPARES 启用或禁用准备语句的模拟。一些驱动程序不支持本机准备语句或对它们的支持有限。使用此设置强制 PDO 始终模拟预准备语句(如果驱动程序支持 TRUE 和模拟准备),或尝试使用本机预准备语句(如果 FALSE)。如果驱动程序无法成功准备当前查询,它将始终回退到模拟准备好的语句。

【讨论】:

我对“准备”的相关性感到困惑。无论是否准备好,“SELECT ...”最终都会发送到服务器,此时服务器会根据请求进行记录。 @RickJames 我很困惑,但似乎 vikash 是正确的。进行此更改后,查询似乎开始出现在摘要中。 [bugs.mysql.com/bug.php?id=80173] 似乎也这么说。 官方回复“在比较 SQL 提示和 C API 的准备语句检测的当前行为后,我们发现在这两种情况下,在准备语句中使用的实际查询的检测是未完成” @vikash-pathak 我在某处读到,如果我这样做,所有字段都将作为字符串返回。有点担心这是否会以某种方式破坏我们现有的应用程序。但是对于我的问题,您的解决方案似乎有效。所以接受

以上是关于Laravel API 的 mysql 查询未在 performance_schema.events_statements_summary_by_digest 中被跟踪的主要内容,如果未能解决你的问题,请参考以下文章

api 端点未在 Sanctum 上进行 CSRF 令牌验证 - CSRF 令牌不匹配

Laravel api 响应时间很慢?

Laravel 完整性约束错误未在控制器中返回 JSON

Laravel 未在 Ubuntu 中加载内页 - 找不到 404

MySQL 未在子查询中使用 INDEX

pymongo 查询未在烧瓶中返回任何内容