EF Core 与 MySQL:日志和调试详解

news/2025/9/18 22:32:59/文章来源:https://www.cnblogs.com/jixingsuiyuan/p/19099782

本文将详细讲解EF Core与MySQL的日志和调试,分为三个部分:EF Core日志配置、MySQL日志查看以及使用调试工具分析查询性能。

1. 配置 EF Core 日志

基本日志配置

// 在DbContext配置中启用日志记录
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{var connectionString = "server=localhost;database=efcoredb;user=root;password=yourpassword";optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)).EnableSensitiveDataLogging() // 记录参数值(仅开发环境).EnableDetailedErrors() // 提供更详细的错误信息(仅开发环境).LogTo(Console.WriteLine, LogLevel.Information) // 输出到控制台
        .LogTo(message => Debug.WriteLine(message), // 输出到调试输出
            LogLevel.Debug);
}

使用 ILoggerFactory(ASP.NET Core 应用)

// 在Program.cs或Startup.cs中配置
public void ConfigureServices(IServiceCollection services)
{services.AddDbContext<ApplicationDbContext>(options =>{var connectionString = Configuration.GetConnectionString("DefaultConnection");options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)).EnableSensitiveDataLogging(Environment.IsDevelopment()).EnableDetailedErrors(Environment.IsDevelopment()).UseLoggerFactory(LoggerFactory.Create(builder =>{builder.AddConsole().AddDebug().AddFilter(DbLoggerCategory.Database.Command.Name, LogLevel.Information);}));});
}

自定义日志过滤器

// 只记录执行时间超过100ms的查询
optionsBuilder.LogTo(message =>{if (message.Contains("CommandExecuted") && message.Contains("Elapsed")){var elapsedMatch = Regex.Match(message, @"Elapsed:(\d+)ms");if (elapsedMatch.Success && int.Parse(elapsedMatch.Groups[1].Value) > 100){Console.WriteLine($"慢查询: {message}");}}},LogLevel.Information
);

结构化日志记录

// 使用Serilog等结构化日志框架
Log.Logger = new LoggerConfiguration().MinimumLevel.Information().WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}").WriteTo.File("logs/efcore-.txt", rollingInterval: RollingInterval.Day).CreateLogger();services.AddDbContext<ApplicationDbContext>(options =>
{options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)).LogTo(Log.Logger.Information, LogLevel.Information).LogTo(Log.Logger.Warning, LogLevel.Warning).LogTo(Log.Logger.Error, LogLevel.Error);
});

2. 查看 MySQL 日志

启用和配置 MySQL 日志

-- 查看当前日志配置
SHOW VARIABLES LIKE '%log%';-- 启用通用查询日志(记录所有查询)
SET GLOBAL general_log = 'ON';
SET GLOBAL general_log_file = '/var/log/mysql/general.log';-- 启用慢查询日志
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
SET GLOBAL long_query_time = 1; -- 超过1秒的查询视为慢查询-- 启用二进制日志(用于复制和恢复)
SET GLOBAL log_bin = 'ON';-- 启用错误日志(通常默认开启)
SHOW VARIABLES LIKE 'log_error';

在 MySQL 配置文件中设置日志

# /etc/mysql/my.cnf 或 /etc/mysql/mysql.conf.d/mysqld.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# 错误日志
log_error = /var/log/mysql/error.log# 二进制日志
log_bin = /var/log/mysql/mysql-bin.log
expire_logs_days = 10
max_binlog_size = 100M

分析 MySQL 日志

# 查看慢查询日志
sudo tail -f /var/log/mysql/slow.log# 使用mysqldumpslow分析慢查询日志
sudo mysqldumpslow /var/log/mysql/slow.log# 按执行时间排序查看最慢的查询
sudo mysqldumpslow -s t /var/log/mysql/slow.log# 查看通用查询日志
sudo tail -f /var/log/mysql/general.log# 使用pt-query-digest分析查询(需要安装Percona Toolkit)
sudo pt-query-digest /var/log/mysql/slow.log

在应用程序中记录 MySQL 性能指标

// 创建性能监控服务
public class MySqlPerformanceMonitor
{private readonly ApplicationDbContext _context;private readonly ILogger<MySqlPerformanceMonitor> _logger;public MySqlPerformanceMonitor(ApplicationDbContext context, ILogger<MySqlPerformanceMonitor> logger){_context = context;_logger = logger;}public async Task MonitorQueryPerformanceAsync(Func<Task> databaseOperation, string operationName){var stopwatch = Stopwatch.StartNew();try{await databaseOperation();stopwatch.Stop();if (stopwatch.ElapsedMilliseconds > 1000) // 超过1秒的记录为警告
            {_logger.LogWarning("慢查询检测: {Operation} 耗时 {ElapsedMs}ms", operationName, stopwatch.ElapsedMilliseconds);}else if (stopwatch.ElapsedMilliseconds > 500) // 超过0.5秒的记录为信息
            {_logger.LogInformation("查询性能: {Operation} 耗时 {ElapsedMs}ms", operationName, stopwatch.ElapsedMilliseconds);}}catch (Exception ex){stopwatch.Stop();_logger.LogError(ex, "查询执行失败: {Operation} 耗时 {ElapsedMs}ms", operationName, stopwatch.ElapsedMilliseconds);throw;}}
}

3. 使用调试工具分析查询性能

使用 EF Core 的诊断工具

// 启用诊断监听器
DiagnosticListener.AllListeners.Subscribe(new EfCoreDiagnosticListener());public class EfCoreDiagnosticListener : IObserver<DiagnosticListener>
{public void OnNext(DiagnosticListener value){if (value.Name == DbLoggerCategory.Name){value.Subscribe(new EfCoreObserver());}}public void OnCompleted() { }public void OnError(Exception error) { }
}public class EfCoreObserver : IObserver<KeyValuePair<string, object>>
{public void OnNext(KeyValuePair<string, object> value){if (value.Key == RelationalEventId.CommandExecuted.Name){var command = (IDbCommand)value.Value.GetType().GetProperty("Command").GetValue(value.Value);var duration = (TimeSpan)value.Value.GetType().GetProperty("Duration").GetValue(value.Value);if (duration.TotalMilliseconds > 100){Debug.WriteLine($"慢查询: {command.CommandText} 耗时: {duration.TotalMilliseconds}ms");}}}public void OnCompleted() { }public void OnError(Exception error) { }
}

使用 Application Insights 监控

// 在Startup.cs中配置Application Insights
public void ConfigureServices(IServiceCollection services)
{services.AddApplicationInsightsTelemetry(Configuration["APPLICATIONINSIGHTS_CONNECTION_STRING"]);services.AddDbContext<ApplicationDbContext>(options =>{options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)).EnableSensitiveDataLogging().AddApplicationInsightsDiagnostics(); // 如果支持的话
    });
}// 或者手动记录依赖跟踪
public async Task<List<Product>> GetProductsAsync()
{var operation = telemetryClient.StartOperation<DependencyTelemetry>("MySQL Query");operation.Telemetry.Type = "MySQL";operation.Telemetry.Data = "SELECT * FROM Products";try{var products = await _context.Products.ToListAsync();operation.Telemetry.Success = true;return products;}catch (Exception ex){operation.Telemetry.Success = false;telemetryClient.TrackException(ex);throw;}finally{telemetryClient.StopOperation(operation);}
}

使用 MiniProfiler

// 安装MiniProfiler.EntityFrameworkCore
// 在Startup.cs中配置
public void ConfigureServices(IServiceCollection services)
{services.AddMiniProfiler(options =>{options.RouteBasePath = "/profiler";options.ColorScheme = StackExchange.Profiling.ColorScheme.Auto;options.EnableMvcFilterProfiling = true;options.EnableMvcViewProfiling = true;options.TrackConnectionOpenClose = true;}).AddEntityFramework();
}public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseMiniProfiler();// ... 其他中间件
}// 在视图中添加MiniProfiler
@inject StackExchange.Profiling.MiniProfiler Profiler
@MiniProfiler.RenderIncludes(Profiler)

使用 JetBrains dotTrace 或 dotMemory

// 在代码中添加性能分析点
public async Task<List<Product>> GetExpensiveProductsAsync()
{// 使用JetBrains Profiler API(需要安装JetBrains.Profiler.Api包)
    JetBrains.Profiler.Api.MeasureProfiler.StartCollectingData();try{var products = await _context.Products.Where(p => p.Price > 100).Include(p => p.Category).ToListAsync();return products;}finally{JetBrains.Profiler.Api.MeasureProfiler.SaveData();}
}

使用 MySQL EXPLAIN 分析查询计划

// 在代码中执行EXPLAIN分析查询
public async Task<string> ExplainQueryAsync(IQueryable query)
{var sql = query.ToQueryString();var explainSql = $"EXPLAIN {sql}";using (var command = _context.Database.GetDbConnection().CreateCommand()){command.CommandText = explainSql;_context.Database.OpenConnection();using (var result = await command.ExecuteReaderAsync()){var explanation = new StringBuilder();while (await result.ReadAsync()){for (int i = 0; i < result.FieldCount; i++){explanation.AppendLine($"{result.GetName(i)}: {result.GetValue(i)}");}explanation.AppendLine("---");}return explanation.ToString();}}
}// 使用方式
var query = _context.Products.Where(p => p.Price > 100);
var explanation = await ExplainQueryAsync(query);
Console.WriteLine(explanation);

使用 Visual Studio 的调试工具

// 在Visual Studio中使用诊断工具
// 1. 打开"诊断工具"窗口(调试 -> 窗口 -> 显示诊断工具)
// 2. 开始调试并记录性能
// 3. 分析CPU使用率、内存分配和数据库查询// 使用条件断点调试特定查询
var products = _context.Products.Where(p => p.Price > 100) // 在这里设置条件断点:p.Price > 1000
    .ToList();// 使用即时窗口测试查询
// 在调试期间,可以在即时窗口中执行:
// _context.Products.Where(p => p.Price > 100).ToList()

创建自定义性能分析中间件

// ASP.NET Core中间件,用于记录所有数据库操作
public class QueryPerformanceMiddleware
{private readonly RequestDelegate _next;private readonly ILogger<QueryPerformanceMiddleware> _logger;public QueryPerformanceMiddleware(RequestDelegate next, ILogger<QueryPerformanceMiddleware> logger){_next = next;_logger = logger;}public async Task InvokeAsync(HttpContext context, ApplicationDbContext dbContext){var stopwatch = Stopwatch.StartNew();var originalQueryTrackingBehavior = dbContext.ChangeTracker.QueryTrackingBehavior;try{// 设置为NoTracking以提高性能,除非需要修改数据dbContext.ChangeTracker.QueryTrackingBehavior = QueryTrackingBehavior.NoTracking;await _next(context);}finally{stopwatch.Stop();dbContext.ChangeTracker.QueryTrackingBehavior = originalQueryTrackingBehavior;// 记录请求处理时间和数据库查询统计_logger.LogInformation("请求 {Method} {Path} 处理时间: {ElapsedMs}ms, 数据库查询次数: {QueryCount}",context.Request.Method, context.Request.Path, stopwatch.ElapsedMilliseconds,dbContext.GetQueryCount());}}
}// 扩展方法获取查询次数
public static class DbContextExtensions
{public static int GetQueryCount(this DbContext context){// 这种方法可能不准确,更好的方式是使用诊断监听器return 0; // 实际实现需要更复杂的方法
    }
}// 在Startup.cs中注册中间件
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{app.UseMiddleware<QueryPerformanceMiddleware>();// ... 其他中间件
}

总结

本教程详细介绍了EF Core与MySQL的日志记录和调试技术,包括:

  1. 配置EF Core日志:

    • 基本日志配置和敏感数据记录

    • 使用ILoggerFactory集成ASP.NET Core日志系统

    • 自定义日志过滤器和结构化日志记录

  2. 查看MySQL日志:

    • 启用和配置各种MySQL日志(通用查询、慢查询、错误日志)

    • 分析MySQL日志以识别性能问题

    • 在应用程序中集成MySQL性能监控

  3. 使用调试工具分析查询性能:

    • EF Core诊断工具和监听器

    • Application Insights集成

    • MiniProfiler实时性能分析

    • JetBrains专业分析工具

    • MySQL EXPLAIN查询计划分析

    • Visual Studio调试工具

    • 自定义性能分析中间件

通过这些工具和技术,我们可以:

  • 识别和解决性能瓶颈

  • 优化数据库查询

  • 监控应用程序的健康状况

  • 诊断和解决生产环境中的问题

建议在开发环境中启用详细日志记录和性能分析,而在生产环境中则使用更保守的配置,只记录警告和错误,并定期检查慢查询日志以识别需要优化的查询。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/907480.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用镜像源解决github拉取代码问题 - GD

命令行输入以下语句: git config --global url."https://gitclone.com/github.com/".insteadOf "https://github.com/" 取消设置: git config --global --unset url."https://gitclone.com…

实用指南:uniapp打包前端项目

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

类和面向对象

概述:语言特性有二,其一为既面向过程又面向对象,其二为用类和对象表示数据和操作数据的,c++将操作和数据汇聚成类和对象何为对象?即世间的一切事物。假如一个对象为feijib,则可以说这个为类feijib,难道类是对象…

PHP转Go系列 | PHP8 这些新函数让你眼前一亮

说实话,PHP8 中的这三个新函数让字符串检查,变得非常直观,就像让代码说人话一样。这对我们程序员来说是一件大好事,提升可读性,减少 Bug 量,升级到 PHP8 之后,再也不用维护类似的屎山代码了。大家好,我是码农先…

代码随想录算法训练营第二天 |209.长度最小的子数组,59. 螺旋矩阵 II

209.长度最小的子数组 思路:快慢指针的思想,当快指针一直移动的时候,那么数列一定是递增的,且我们要求的是连续的数组,所以我们其实可以一次性用一个for就给全部遍历完成。当我们这个区间的值大于了target,我们就…

mac更新or安装homebrew失败

错误信息:fatal: unable to access https://github.com/Homebrew/brew/: LibreSSL SSL_read: error:02FFF03C:system library:func(4095):Operation timed out, errno 60可以用命令:/bin/zsh -c "$(curl -fsSL …

虚拟机5

虚拟机<5>我的虚拟机设置的三个节点,分别为hadoop020,hadoop021,hadoop022,对应教程中的hadoop01,hadoop02,hadoop03

微信小程序实现-单选-以及全选功能。 - 教程

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Typescript中闭包的原理 - 教程

Typescript中闭包的原理 - 教程pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco&quo…

CF2048H Kevin and Strange Operation

操作的自由度很大,打表可以发现限制操作的位置只增不减也是对的。 考虑怎么判断一个串 \(t\) 是否合法。 观察到对于一个位置 \(i\) 满足 \(s_i=0\),想要通过操作使 \(s_i\) 变为 \(1\),只需要 \(>i\) 的位置删掉…

Hadoop本地库加载问题分析与解决方案

主要问题分析 ​​本地库加载警告​​: WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable 这表明Hadoop无法正确加载本地优化库…

GO基础总结

环境搭建 基本语法 参见:https://www.cnblogs.com/vonlinee/p/19005628 工具链

Visual Studio 离线安装0x80131509

Visual Studio 2026在本月发布了,它最大的特点是集成了GitHub Copilot,内置AI编程,空了要尝尝鲜(使用过Visual Studio Code的Copilot,还是挺有用的)。目前,VS2022很少使用,像VS2012一样被跳过,主要使用VS2019…

dash 从入门到精通

dash 从入门到精通目录 官方地址:https://plotly.com/dash/ Github 开源地址:https://github.com/plotly/dash Dash 官方文档:https://dash.plotly.com/

Oracle备份恢复:backup as copy保留文件名不变化,只更改路径名

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。Oracle备份恢…

读书笔记:数据库中的预连接神器:位图连接索引

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。本文为个人学…

飞算JavaAI:专为Java开发者打造的智能编程革命 - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

故障处理:CRS无法随操作系统自动启动故障案例分享

我们的文章会在微信公众号IT民工的龙马人生和博客网站( www.htz.pw )同步更新 ,欢迎关注收藏,也欢迎大家转载,但是请在文章开始地方标注文章出处,谢谢! 由于博客中有大量代码,通过页面浏览效果更佳。今天分享一个…

02020401 EF Core基础01-EF Core简介和开发环境搭建、实体类、配置类、继承DbContex的类、Migration包的使用

02020401 EF Core基础01-EF Core简介和开发环境搭建、实体类、配置类、继承DbContex的类、Migration包的使用 1. EF Core简介(视频3-1)本课程需要你有数据库、SQL等基础知识。关系数据库:MySql、SQL Server、Oracle…