10 câu hỏi có thể gặp khi phỏng vấn
Chọn theo kỹ năng và cấp của tin (C# & .NET, Java, SQL & Database). Gợi ý trả lời do Drama Công Ty biên soạn để bạn ôn nhanh, không phải đề của công ty.
01Lỗi N+1 query trong Entity Framework Core là gì và xử lý thế nào?C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →N+1 là khi lấy danh sách N bản ghi bằng 1 query, rồi mỗi bản ghi lại phát sinh thêm 1 query để lấy dữ liệu liên quan, thường do lazy loading hoặc truy vấn trong vòng lặp.
Cách xử lý:
- Eager loading:
.Include(o => o.Items). - Tốt hơn nữa là projection chỉ lấy cột cần:
.Select(o => new OrderDto(o.Id, o.Items.Count)). - Include nhiều collection gây "cartesian explosion" thì dùng
.AsSplitQuery(). - Màn hình chỉ đọc thì thêm
.AsNoTracking()để giảm chi phí change tracking.
Để phát hiện, bật log SQL của EF Core khi phát triển, hoặc dùng công cụ APM xem số query mỗi request.
Người phỏng vấn muốn nghe: bạn kiểm tra SQL thực sự được sinh ra thay vì tin LINQ trông gọn là chạy nhanh.
- Eager loading:
02Garbage Collector của .NET hoạt động thế nào? Khi nào cần IDisposable?C# & .NET
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →GC quản lý heap theo thế hệ: object mới ở Gen 0, sống sót qua lần thu gom thì lên Gen 1, Gen 2. Phần lớn object chết trẻ nên thu gom Gen 0 rất rẻ. Object lớn (khoảng từ 85 KB) vào Large Object Heap và chỉ được thu cùng Gen 2.
GC chỉ thu hồi bộ nhớ managed. Tài nguyên khác như file, socket, kết nối DB cần giải phóng chủ động qua
IDisposable:await using var conn = new NpgsqlConnection(cs); using var stream = File.OpenRead(path);- Finalizer chỉ là lưới an toàn, chạy không xác định thời điểm và tốn chi phí.
Hay sai: tạo mới
HttpClientcho mỗi request rồi dispose, dễ cạn socket. Hãy dùngIHttpClientFactoryhoặc một instance dùng chung.03Ứng dụng ASP.NET Core bị memory leak hoặc CPU cao trên production. Bạn điều tra thế nào?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Thu thập số liệu trước, đoán sau: xem metrics, chụp dump hoặc trace, rồi phân tích.
- Theo dõi bằng
dotnet-counters: heap size, số lần GC từng gen, thread pool queue length, exception rate. - Leak bộ nhớ: chụp hai lần
dotnet-gcdumphoặcdotnet-dumpcách nhau một khoảng, so sánh loại object tăng và tìm ai đang giữ tham chiếu. - CPU cao hoặc treo:
dotnet-traceđể xem hot path; thread pool queue tăng thường do sync-over-async.
Nguyên nhân hay gặp: event handler không gỡ đăng ký, cache static không giới hạn kích thước, giữ
DbContextquá lâu, regex hoặc serialize lặp lại trong vòng lặp nóng.Người phỏng vấn muốn nghe: một ca thực tế bạn từng xử lý, công cụ đã dùng và kết quả trước/sau.
- Theo dõi bằng
04Bộ nhớ JVM gồm những vùng nào? Garbage Collector hoạt động ra sao và Java có bị memory leak không?Java
Gợi ý trả lời
Ôn thêm câu hỏi Java →Hai vùng chính: stack (mỗi thread một stack, chứa biến cục bộ và tham chiếu) và heap (chứa object, dùng chung). Ngoài ra có Metaspace chứa thông tin class.
- GC tìm các object không còn được tham chiếu từ "GC roots" (biến trên stack, field static...) và thu hồi.
- Heap chia theo thế hệ: object mới nằm ở young generation, sống lâu thì được chuyển lên old generation.
- G1 là GC mặc định; ZGC hợp khi cần pause rất ngắn với heap lớn.
Java vẫn leak khi object không dùng nữa mà vẫn còn tham chiếu:
- Cache hoặc
static Mapchỉ thêm, không bao giờ xoá. ThreadLocalkhôngremove()trong thread pool.- Listener đăng ký mà không huỷ.
Người phỏng vấn muốn nghe: phân biệt được
OutOfMemoryError: Java heap spacevới lỗi Metaspace, và biết dùng heap dump để tìm ai đang giữ object.05Virtual threads trong Java 21 là gì? Khi nào nên dùng và cần lưu ý gì?Java · Senior
Gợi ý trả lời
Ôn thêm câu hỏi Java →Virtual thread là thread nhẹ do JVM quản lý, được gắn lên một số ít platform thread (carrier). Khi gặp I/O blocking, nó nhả carrier để chạy việc khác, nên bạn có thể có hàng trăm nghìn thread mà vẫn viết code blocking dễ đọc.
try (var executor = Executors.newVirtualThreadPerTaskExecutor()) { ids.forEach(id -> executor.submit(() -> callApi(id))); }- Hợp với tải nhiều I/O (gọi DB, HTTP). Không giúp gì với tác vụ nặng CPU.
- Spring Boot 3.2+ bật bằng
spring.threads.virtual.enabled=true. - Không đưa virtual thread vào pool: tạo mới cho mỗi task là cách dùng đúng.
- Giới hạn tài nguyên (connection pool DB) vẫn là giới hạn thật; dùng
Semaphorenếu cần. - Trên Java 21, blocking bên trong
synchronizedcó thể "pin" carrier; các bản JDK mới hơn đã cải thiện. Cẩn thận vớiThreadLocalchứa object lớn.
Người phỏng vấn muốn nghe: virtual threads tăng throughput, không làm từng request nhanh hơn.
06Deadlock trong database xảy ra thế nào và xử lý ra sao?SQL & Database · Senior
Gợi ý trả lời
Ôn thêm câu hỏi SQL & Database →Deadlock là khi hai transaction giữ khoá mà bên kia cần và chờ nhau mãi. DB tự phát hiện, chọn một transaction làm nạn nhân và rollback nó.
Ví dụ: T1 khoá dòng A rồi muốn B, cùng lúc T2 khoá B rồi muốn A.
Cách giảm deadlock:
- Luôn khoá tài nguyên theo cùng một thứ tự (vd. sắp xếp theo
idtrước khi update nhiều dòng). - Giữ transaction ngắn, không chờ I/O bên ngoài khi đang giữ khoá.
- Có index phù hợp để câu
UPDATE/DELETEkhông khoá quá nhiều dòng. - Ứng dụng bắt lỗi deadlock và retry có giới hạn.
Khi điều tra: MySQL dùng
SHOW ENGINE INNODB STATUS, PostgreSQL xem log (deadlock được ghi kèm câu lệnh) vàpg_locks.Người phỏng vấn muốn nghe: bạn coi retry là bình thường nhưng vẫn tìm gốc rễ ở thứ tự khoá.
- Luôn khoá tài nguyên theo cùng một thứ tự (vd. sắp xếp theo
07Xử lý concurrency khi nhiều request cùng cập nhật một bản ghi trong EF Core thế nào?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Hai hướng chính: optimistic concurrency (phát hiện xung đột khi lưu) và pessimistic (khoá trước khi sửa).
Optimistic với EF Core: đánh dấu một cột làm concurrency token, EF thêm điều kiện so sánh vào
UPDATEvà némDbUpdateConcurrencyExceptionnếu không có dòng nào bị cập nhật.public class Product { public int Stock { get; set; } [Timestamp] public byte[] RowVersion { get; set; } = []; }- Bắt exception, tải lại dữ liệu, rồi retry hoặc báo người dùng.
- PostgreSQL thường dùng cột hệ thống
xminlàm token. - Trường hợp đơn giản như trừ tồn kho có thể dùng một câu
ExecuteUpdateAsyncatomic kèm điều kiệnStock >= qty.
Người phỏng vấn muốn nghe: bạn cân nhắc mức độ tranh chấp: thấp thì optimistic, cao và nghiệp vụ quan trọng thì khoá hoặc đưa vào hàng đợi.
08Bạn tối ưu hiệu năng một Web API .NET chịu tải cao thế nào?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Bắt đầu bằng đo đạc (load test, APM, profiler), sau đó xử lý các điểm nghẽn phổ biến theo thứ tự tác động.
- I/O: async xuyên suốt, không sync-over-async; dùng connection pool đúng cách.
- Database: projection,
AsNoTracking, index đúng, tránh N+1; với bulk update dùngExecuteUpdateAsync. - Cache:
IMemoryCache, distributed cache (Redis),HybridCachetừ .NET 9, output caching cho response công khai. - Cấp phát bộ nhớ: giảm object tạm trong hot path, dùng
Span<T>,ArrayPool,System.Text.Jsonvới source generator. - Hạ tầng: response compression, rate limiting middleware, scale ngang khi stateless.
Luôn so sánh số liệu trước và sau (p95 latency, throughput, CPU, GC). Micro-optimize nên đo bằng BenchmarkDotNet.
Hay sai: tối ưu code C# trong khi 90% thời gian nằm ở query DB.
09Bạn tổ chức một dự án .NET lớn thế nào? Clean Architecture có luôn cần thiết?C# & .NET · Senior
Gợi ý trả lời
Ôn thêm câu hỏi C# & .NET →Mục tiêu là tách nghiệp vụ khỏi chi tiết hạ tầng để dễ test và dễ thay đổi; mức độ tách nên tương xứng với độ phức tạp của dự án.
Clean Architecture điển hình có các project: Domain (entity, rule), Application (use case, interface), Infrastructure (EF Core, gửi mail, gọi API ngoài), Api (controller hoặc minimal API). Phụ thuộc chỉ hướng vào trong.
- Dịch vụ CRUD nhỏ thì cách tổ chức theo vertical slice (mỗi tính năng một thư mục) thường gọn hơn và ít boilerplate.
- Tránh bọc thêm repository chung chung lên EF Core nếu nó chỉ chuyển tiếp lời gọi.
- MediatR hay CQRS là công cụ, không phải yêu cầu bắt buộc.
Người phỏng vấn muốn nghe: bạn hiểu trade-off giữa số lớp trừu tượng và tốc độ phát triển, và nêu được lý do cho lựa chọn trong dự án gần nhất.
10Bạn phản ứng thế nào khi nhận góp ý tiêu cực về công việc của mình?Câu hỏi hành vi & văn hoá
Gợi ý trả lời
Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →Cho thấy bạn tách góp ý khỏi cảm xúc cá nhân và biến nó thành hành động.
- Lắng nghe hết, hỏi lại để hiểu ví dụ cụ thể và kỳ vọng.
- Cảm ơn, kể cả khi chưa đồng ý hoàn toàn; nếu có góc nhìn khác, trao đổi bằng thông tin, không phòng thủ.
- Lên kế hoạch cải thiện và chủ động xin phản hồi lại sau một thời gian.
Câu mẫu: "Có lần lead góp ý code review của em quá dài, khó review. Lúc đầu em hơi chột dạ, nhưng em hỏi anh muốn chia thế nào cho dễ. Từ đó em tách pull request nhỏ theo từng thay đổi, thời gian review của team giảm hẳn và em cũng ít bị yêu cầu sửa lại hơn."
Hay sai: nói "em luôn vui vẻ đón nhận mọi góp ý" mà không có ví dụ.
Bạn đã phỏng vấn ở Usol Vietnam?
Kể lại các vòng và câu hỏi đã gặp (ẩn danh) để người sau ôn đúng trọng tâm.
Chia sẻ kinh nghiệm phỏng vấn