Skip to content

Commit

Permalink
Add More examples (#133)
Browse files Browse the repository at this point in the history
* add goroutine text

* update

* fix funclatency

* update doc

* update about nginx

* update nginx

* u[date co

* fix compile

* update

* fix
  • Loading branch information
yunwei37 authored Sep 2, 2024
1 parent 9c2bba3 commit 2f3ed55
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 6 deletions.
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,19 @@ Android:

- [Using eBPF programs on Android](src/22-android/README_en.md)

Networking and tracing:
Networking:

- [Tracing HTTP requests or other layer-7 protocols using eBPF socket filter or syscall trace](src/23-http/README_en.md)
- [Accelerating network request forwarding using sockops](src/29-sockops/README_en.md)
- [Capturing Plain Text Data of Various Libraries' SSL/TLS Using uprobe](src/30-sslsniff/README_en.md)
- [Accelerating network request forwarding using sockops](src/29-sockops/README.md)

tracing:

- [Tracing HTTP requests or other layer-7 protocols using eBPF socket filter or syscall trace](src/23-http/README.md)
- [Capturing Plain Text Data of Various Libraries' SSL/TLS Using uprobe](src/30-sslsniff/README.md)
- [Using eBPF to Trace Go Routine States](src/31-goroutine/README.md)
- [Measuring Function Latency with eBPF](src/33-funclatency/README.md)
- [Use uprobe to trace Rust programs](src/37-uprobe-rust/README.md)
- [Using eBPF to Trace Nginx Requests](src/39-nginx/README.md)
- [Using eBPF to Trace MySQL Queries](src/40-mysql)

Security:

Expand Down
105 changes: 105 additions & 0 deletions src/40-mysql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# 使用 eBPF 跟踪 MySQL 查询

MySQL 是全球最广泛使用的关系型数据库管理系统之一。无论您是在运行小型应用程序还是大型企业系统,了解 MySQL 数据库的性能特征都至关重要。特别是了解 SQL 查询的执行时间以及哪些查询占用了最多的时间,有助于诊断性能问题,并优化数据库以提高效率。

在这种情况下,eBPF(扩展的伯克利包过滤器)可以派上用场。eBPF 是一项强大的技术,它允许您编写程序并在 Linux 内核中运行,帮助您跟踪、监控和分析系统行为的各个方面,包括 MySQL 这类应用程序的性能。在本文中,我们将探讨如何使用 eBPF 跟踪 MySQL 查询,测量其执行时间,并深入了解数据库的性能表现。

## 背景:MySQL 和 eBPF

### MySQL

MySQL 是一种关系型数据库管理系统(RDBMS),使用结构化查询语言(SQL)来管理和查询数据。它广泛应用于各种场景,从 Web 应用程序到数据仓库。MySQL 的性能对应用程序的整体性能至关重要,尤其是在处理大数据集或复杂查询时。

### eBPF

eBPF 是一项允许在 Linux 内核中执行自定义程序的技术,而无需修改内核源代码或加载内核模块。eBPF 最初是为网络数据包过滤而设计的,但现在已经发展为一个多用途的工具,可用于性能监控、安全和调试。eBPF 程序可以附加到各种内核和用户空间事件上,使得我们能够跟踪函数、系统调用等的执行。

使用 eBPF,我们可以跟踪 MySQL 的某些函数,例如负责处理 SQL 查询的 `dispatch_command` 函数。通过跟踪该函数,我们可以捕获查询执行的开始和结束时间,测量延迟,并记录执行的查询。

## MySQL 查询

要使用 eBPF 跟踪 MySQL 查询,我们可以编写一个使用 `bpftrace` 的脚本,`bpftrace` 是一种 eBPF 的高级跟踪语言。以下是一个跟踪 MySQL 中 `dispatch_command` 函数的脚本,用于记录执行的查询并测量其执行时间:

```bt
#!/usr/bin/env bpftrace
// 跟踪 MySQL 中的 dispatch_command 函数
uprobe:/usr/sbin/mysqld:dispatch_command
{
// 将命令执行的开始时间存储在 map 中
@start_times[tid] = nsecs;
// 打印进程 ID 和命令字符串
printf("MySQL command executed by PID %d: ", pid);
// dispatch_command 的第三个参数是 SQL 查询字符串
printf("%s\n", str(arg3));
}
uretprobe:/usr/sbin/mysqld:dispatch_command
{
// 从 map 中获取开始时间
$start = @start_times[tid];
// 计算延迟,以毫秒为单位
$delta = (nsecs - $start) / 1000000;
// 打印延迟
printf("Latency: %u ms\n", $delta);
// 从 map 中删除条目以避免内存泄漏
delete(@start_times[tid]);
}
```

### 脚本解释

1. **跟踪 `dispatch_command` 函数**
- 该脚本在 MySQL 中的 `dispatch_command` 函数上附加了一个 `uprobe`。该函数在 MySQL 需要执行 SQL 查询时调用。`Uprobe` 在内核模式 eBPF 运行时中可能会导致较大的性能开销。在这种情况下,您可以考虑使用用户模式 eBPF 运行时,例如 [bpftime](https://github.com/eunomia-bpf/bpftime)
- `uprobe` 捕获函数执行的开始时间并记录正在执行的 SQL 查询。

2. **计算和记录延迟**
- 一个相应的 `uretprobe` 附加到 `dispatch_command` 函数。`uretprobe` 在函数返回时触发,允许我们计算查询的总执行时间(延迟)。
- 延迟以毫秒为单位计算并打印到控制台。

3. **使用 Map 管理状态**
- 脚本使用一个 BPF map 来存储每个查询的开始时间,并以线程 ID (`tid`) 作为键。这使我们能够匹配每次查询执行的开始和结束时间。
- 在计算延迟后,从 map 中删除条目以避免内存泄漏。

## 运行脚本

要运行此脚本,只需将其保存为文件(例如 `trace_mysql.bt`),然后使用 `bpftrace` 执行它:

```bash
sudo bpftrace trace_mysql.bt
```

### 输出示例

脚本运行后,它将打印 MySQL 执行的每个 SQL 查询的信息,包括进程 ID、查询内容以及延迟时间:

```console
MySQL command executed by PID 1234: SELECT * FROM users WHERE id = 1;
Latency: 15 ms
MySQL command executed by PID 1234: UPDATE users SET name = 'Alice' WHERE id = 2;
Latency: 23 ms
MySQL command executed by PID 1234: INSERT INTO orders (user_id, product_id) VALUES (1, 10);
Latency: 42 ms
```

这个输出显示了正在执行的 SQL 命令以及每个命令的执行时间,为您提供了关于 MySQL 查询性能的宝贵见解。

## 跟踪 MySQL 查询可以带来什么收获?

通过使用 eBPF 跟踪 MySQL 查询,您可以获得以下几点收获:

- **识别慢查询**:您可以快速识别哪些 SQL 查询执行时间最长。这对于性能调优以及优化数据库模式或索引策略至关重要。
- **监控数据库性能**:定期监控查询的延迟,确保您的 MySQL 数据库在不同工作负载下保持最佳性能。
- **调试和故障排除**:在面对性能问题时,这种跟踪方法可以帮助您准确定位导致延迟的查询,从而更容易调试和解决问题。
- **容量规划**:通过了解各种查询的延迟,您可以更好地进行容量规划,确保您的 MySQL 数据库能够处理更高的负载或更复杂的查询。

## 结论

eBPF 提供了一种强大的方法来监控和跟踪 MySQL 查询的性能,而无需对系统进行侵入式更改。通过使用 `bpftrace` 这样的工具,您可以实时了解数据库的性能表现,识别潜在的瓶颈,并优化系统以获得更好的性能。

如果您有兴趣了解更多关于 eBPF 的知识,以及如何将其用于监控和优化系统的其他部分,请访问我们的 [https://github.com/eunomia-bpf/bpf-developer-tutorial](https://github.com/eunomia-bpf/bpf-developer-tutorial) 或浏览我们的网站 [https://eunomia.dev/tutorials/](https://eunomia.dev/tutorials/) 获取更多示例和完整的教程。
105 changes: 105 additions & 0 deletions src/40-mysql/README_en.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
# Using eBPF to Trace MySQL Queries

MySQL is one of the most widely used relational database management systems in the world. Whether you are running a small application or a large-scale enterprise system, understanding the performance characteristics of your MySQL database can be crucial. In particular, knowing how long SQL queries take to execute and which queries are consuming the most time can help in diagnosing performance issues and optimizing your database for better efficiency.

This is where eBPF (Extended Berkeley Packet Filter) comes into play. eBPF is a powerful technology that allows you to write programs that can run in the Linux kernel, enabling you to trace, monitor, and analyze various aspects of system behavior, including the performance of applications like MySQL. In this blog, we'll explore how to use eBPF to trace MySQL queries, measure their execution time, and gain valuable insights into your database's performance.

## Background: MySQL and eBPF

### MySQL

MySQL is a relational database management system (RDBMS) that uses Structured Query Language (SQL) to manage and query data. It is widely used for a variety of applications, from web applications to data warehousing. MySQL's performance can be critical to the overall performance of your application, especially when dealing with large datasets or complex queries.

### eBPF

eBPF is a technology that allows for the execution of custom programs in the Linux kernel without the need to modify the kernel source code or load kernel modules. Initially designed for network packet filtering, eBPF has evolved into a versatile tool for performance monitoring, security, and debugging. eBPF programs can be attached to various kernel and user-space events, making it possible to trace the execution of functions, system calls, and more.

Using eBPF, we can trace the execution of MySQL functions, such as `dispatch_command`, which is responsible for handling SQL queries. By tracing this function, we can capture the start and end times of query execution, measure the latency, and log the executed queries.

## Tracing MySQL Queries with eBPF

To trace MySQL queries using eBPF, we can write a script using `bpftrace`, a high-level tracing language for eBPF. Below is a script that traces the `dispatch_command` function in MySQL to log executed queries and measure their execution time:

```bt
#!/usr/bin/env bpftrace
// Trace the dispatch_command function in MySQL
uprobe:/usr/sbin/mysqld:dispatch_command
{
// Store the start time of the command execution in the map
@start_times[tid] = nsecs;
// Print the process ID and command string
printf("MySQL command executed by PID %d: ", pid);
// The third argument to dispatch_command is the SQL query string
printf("%s\n", str(arg3));
}
uretprobe:/usr/sbin/mysqld:dispatch_command
{
// Retrieve the start time from the map
$start = @start_times[tid];
// Calculate the latency in milliseconds
$delta = (nsecs - $start) / 1000000;
// Print the latency
printf("Latency: %u ms\n", $delta);
// Delete the entry from the map to avoid memory leaks
delete(@start_times[tid]);
}
```

### Explanation of the Script

1. **Tracing the `dispatch_command` Function**:
- The script attaches an `uprobe` to the `dispatch_command` function in MySQL. This function is called whenever MySQL needs to execute a SQL query. `Uprobe` in kernel mode eBPF runtime may also cause relatively large performance overhead. In this case, you can also consider using user mode eBPF runtime, such as [bpftime](https://github.com/eunomia-bpf/bpftime).
- The `uprobe` captures the start time of the function execution and logs the SQL query being executed.

2. **Calculating and Logging Latency**:
- A corresponding `uretprobe` is attached to the `dispatch_command` function. The `uretprobe` triggers when the function returns, allowing us to calculate the total execution time (latency) of the query.
- The latency is calculated in milliseconds and printed to the console.

3. **Managing State with Maps**:
- The script uses a BPF map to store the start times of each query, keyed by the thread ID (`tid`). This allows us to match the start and end of each query execution.
- After calculating the latency, the entry is removed from the map to avoid memory leaks.

## Running the Script

To run this script, simply save it to a file (e.g., `trace_mysql.bt`), and then execute it using `bpftrace`:

```bash
sudo bpftrace trace_mysql.bt
```

### Sample Output

Once the script is running, it will print information about each SQL query executed by MySQL, including the process ID, the query itself, and the latency:

```console
MySQL command executed by PID 1234: SELECT * FROM users WHERE id = 1;
Latency: 15 ms
MySQL command executed by PID 1234: UPDATE users SET name = 'Alice' WHERE id = 2;
Latency: 23 ms
MySQL command executed by PID 1234: INSERT INTO orders (user_id, product_id) VALUES (1, 10);
Latency: 42 ms
```

This output shows the SQL commands being executed and how long each one took, providing valuable insights into the performance of your MySQL queries.

## What Can We Learn from Tracing MySQL?

By tracing MySQL queries with eBPF, you can gain several insights:

- **Identify Slow Queries**: You can quickly identify which SQL queries are taking the longest to execute. This is critical for performance tuning and optimizing your database schema or indexing strategies.
- **Monitor Database Performance**: Regularly monitor the latency of queries to ensure that your MySQL database is performing optimally under different workloads.
- **Debugging and Troubleshooting**: When facing performance issues, this tracing method can help you pinpoint the exact queries causing delays, making it easier to troubleshoot and resolve issues.
- **Capacity Planning**: By understanding the latency of various queries, you can better plan for capacity, ensuring that your MySQL database can handle increased load or more complex queries.

## Conclusion

eBPF provides a powerful way to monitor and trace the performance of MySQL queries without making intrusive changes to your system. By using tools like `bpftrace`, you can gain real-time insights into how your database is performing, identify potential bottlenecks, and optimize your system for better performance.

If you're interested in learning more about eBPF and how it can be used to monitor and optimize other parts of your system, be sure to check out our [https://github.com/eunomia-bpf/bpf-developer-tutorial](https://github.com/eunomia-bpf/bpf-developer-tutorial) or visit our [https://eunomia.dev/tutorials/](https://eunomia.dev/tutorials/) for more examples and complete tutorials.
30 changes: 30 additions & 0 deletions src/40-mysql/dispatch_command.bt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#!/usr/bin/env bpftrace


// Trace the dispatch_command function in MySQL
uprobe:/usr/sbin/mysqld:dispatch_command
{
// Store the start time of the command execution in the map
@start_times[tid] = nsecs;

// Print the process ID and command string
printf("MySQL command executed by PID %d: ", pid);

// The third argument to dispatch_command is the SQL query string
printf("%s\n", str(arg3));
}

uretprobe:/usr/sbin/mysqld:dispatch_command
{
// Retrieve the start time from the map
$start = @start_times[tid];

// Calculate the latency in milliseconds
$delta = (nsecs - $start) / 1000000;

// Print the latency
printf("Latency: %u ms\n", $delta);

// Delete the entry from the map to avoid memory leaks
delete(@start_times[tid]);
}
8 changes: 6 additions & 2 deletions src/SUMMARY_en.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,19 @@ Android:

- [Using eBPF programs on Android](22-android/README.md)

Networking and tracing:
Networking:

- [Tracing HTTP requests or other layer-7 protocols using eBPF socket filter or syscall trace](23-http/README.md)
- [Accelerating network request forwarding using sockops](29-sockops/README.md)

tracing:

- [Tracing HTTP requests or other layer-7 protocols using eBPF socket filter or syscall trace](23-http/README.md)
- [Capturing Plain Text Data of Various Libraries' SSL/TLS Using uprobe](30-sslsniff/README.md)
- [Using eBPF to Trace Go Routine States](31-goroutine/README.md)
- [Measuring Function Latency with eBPF](33-funclatency/README.md)
- [Use uprobe to trace Rust programs](37-uprobe-rust/README.md)
- [Using eBPF to Trace Nginx Requests](39-nginx/README.md)
- [Using eBPF to Trace MySQL Queries](src/40-mysql)

Security:

Expand Down

0 comments on commit 2f3ed55

Please sign in to comment.