Việc làm

16/09 · Hà Nội · Tại văn phòng

Senior Backend Developer (Java/Springboot) – ID7982

VPBank · Backend Developer

Xem mô tả & ứng tuyển trên ITviecMô tả công việc, lương và ứng tuyển nằm ở ITviec.

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 (SQL & Database, Java). 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.

  1. 01Các isolation level là gì? Dirty read, non-repeatable read, phantom read khác nhau thế nào?SQL & Database

    Gợi ý trả lời

    Isolation level quyết định một transaction thấy được bao nhiêu thay đổi của transaction khác; mức càng cao càng an toàn nhưng càng dễ tranh chấp.

    • Dirty read: đọc dữ liệu transaction khác chưa commit.
    • Non-repeatable read: đọc lại cùng một dòng thấy giá trị đã đổi.
    • Phantom read: chạy lại cùng điều kiện thấy thêm hoặc mất dòng.

    Bốn mức chuẩn: Read Uncommitted, Read Committed, Repeatable Read, Serializable. Mặc định của PostgreSQL, SQL Server, Oracle là Read Committed; MySQL InnoDB là Repeatable Read.

    Thực tế các DB dùng MVCC nên hành vi có khác lý thuyết: Repeatable Read của PostgreSQL dùng snapshot nên không gặp phantom, còn InnoDB dùng gap lock cho câu đọc có khoá.

    Người phỏng vấn muốn nghe: bạn biết DB mình dùng mặc định ở mức nào và đã từng xử lý lost update, vd. bằng SELECT ... FOR UPDATE hoặc optimistic locking.

    Ôn thêm câu hỏi SQL & Database →
  2. 02Một API chạy chậm, nghi do query. Bạn điều tra và tối ưu thế nào?SQL & Database

    Gợi ý trả lời

    Đo trước rồi mới sửa: tìm đúng query chậm, đọc execution plan, rồi chỉnh index hoặc cách viết query.

    1. Bật slow query log (MySQL) hoặc pg_stat_statements (PostgreSQL) để biết query nào tốn thời gian nhất.
    2. Chạy EXPLAIN (PostgreSQL nên dùng EXPLAIN (ANALYZE, BUFFERS)) xem có full scan, ước lượng số dòng lệch nhiều so với thực tế, sort trên đĩa không.
    3. Sửa theo nguyên nhân: thêm hoặc đổi composite index, bỏ hàm bọc cột, chỉ SELECT cột cần, phân trang bằng keyset thay cho OFFSET lớn.
    4. Kiểm tra phía ứng dụng: lỗi N+1 query, thiếu connection pool, lock chờ lâu.
    5. Cập nhật thống kê (ANALYZE) nếu planner ước lượng sai.

    Người phỏng vấn muốn nghe: quy trình có số liệu trước/sau, không phải đoán rồi thêm index bừa.

    Ôn thêm câu hỏi SQL & Database →
  3. 03Chuẩn hoá (normalization) là gì? Khi nào nên denormalize?SQL & Database

    Gợi ý trả lời

    Chuẩn hoá là tách dữ liệu để mỗi thông tin chỉ lưu ở một chỗ, tránh dư thừa và sai lệch khi cập nhật.

    • 1NF: mỗi ô một giá trị nguyên tử, không lưu danh sách trong một cột.
    • 2NF: cột không khoá phụ thuộc vào toàn bộ khoá chính, không chỉ một phần.
    • 3NF: cột không khoá không phụ thuộc bắc cầu qua cột không khoá khác.

    Denormalize khi đọc nhiều hơn ghi rất nhiều và JOIN trở thành điểm nghẽn: lưu sẵn comment_count trong bảng bài viết, chép customer_name vào đơn hàng để giữ đúng tên tại thời điểm đặt, hoặc dựng bảng báo cáo riêng.

    Hay sai: denormalize mà không có cơ chế đồng bộ (trigger, job, event) nên số liệu lệch dần. Hãy nói rõ cái giá phải trả là logic ghi phức tạp hơn.

    Ôn thêm câu hỏi SQL & Database →
  4. 04Lỗi N+1 query trong JPA/Hibernate là gì và xử lý ra sao?Java

    Gợi ý trả lời

    N+1 xảy ra khi bạn lấy N bản ghi bằng 1 query, rồi mỗi lần truy cập quan hệ lazy lại phát sinh thêm 1 query. Ví dụ lấy 100 đơn hàng, rồi gọi order.getCustomer() trong vòng lặp là thành 101 query.

    Cách xử lý:

    • JOIN FETCH trong JPQL: select o from Order o join fetch o.customer.
    • @EntityGraph(attributePaths = "customer") trên method của repository.
    • @BatchSize hoặc hibernate.default_batch_fetch_size để gom lazy load thành câu IN (...).
    • Với màn hình chỉ đọc, trả thẳng DTO projection thay vì entity.

    Phát hiện bằng cách bật log SQL (spring.jpa.show-sql hoặc log của Hibernate) khi dev, hoặc dùng thống kê của Hibernate.

    Hay sai: đổi sang FetchType.EAGER cho xong. Cách này chỉ đổi chỗ lỗi và làm mọi truy vấn khác nặng hơn. Fetch join nhiều collection cùng lúc cũng dễ gây tích Descartes.

    Ôn thêm câu hỏi Java →
  5. 05Bộ 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

    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 Map chỉ thêm, không bao giờ xoá.
    • ThreadLocal không remove() 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 space với lỗi Metaspace, và biết dùng heap dump để tìm ai đang giữ object.

    Ôn thêm câu hỏi Java →
  6. 06Deadlock trong database xảy ra thế nào và xử lý ra sao?SQL & Database · Senior

    Gợi ý trả lời

    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 id trướ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/DELETE khô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á.

    Ôn thêm câu hỏi SQL & Database →
  7. 07Khi nào chọn NoSQL (MongoDB, Redis…) thay vì SQL? Trade-off là gì?SQL & Database · Senior

    Gợi ý trả lời

    Chọn theo mô hình truy cập dữ liệu, không theo xu hướng. SQL mạnh ở quan hệ, ràng buộc và transaction; NoSQL mạnh ở schema linh hoạt, mô hình dữ liệu đặc thù hoặc scale ngang dễ hơn.

    • Document (MongoDB): dữ liệu dạng cây, đọc nguyên khối theo một khoá, schema thay đổi thường xuyên.
    • Key-value (Redis): cache, session, rate limit, bộ đếm, hàng đợi nhỏ; dữ liệu chủ yếu nằm trong RAM.
    • Wide-column, time-series, search engine: ghi khối lượng lớn, log, tìm kiếm full-text.

    Trade-off: JOIN và transaction nhiều document hạn chế hoặc đắt hơn, ràng buộc dữ liệu chuyển sang tầng ứng dụng, và phải thiết kế theo query ngay từ đầu.

    Người phỏng vấn muốn nghe: nhiều hệ thống dùng kết hợp, vd. PostgreSQL làm nguồn sự thật, Redis làm cache. PostgreSQL với JSONB cũng đủ cho nhiều nhu cầu "schema linh hoạt".

    Ôn thêm câu hỏi SQL & Database →
  8. 08Bảng có hàng trăm triệu dòng, query ngày càng chậm. Bạn dùng partitioning, sharding hay read replica?SQL & Database · Senior

    Gợi ý trả lời

    Mỗi kỹ thuật giải một vấn đề khác nhau, nên cần xác định điểm nghẽn là đọc, ghi hay kích thước dữ liệu.

    • Read replica: giảm tải đọc. Phải chấp nhận replication lag; luồng vừa ghi xong đọc lại nên đọc từ primary.
    • Partitioning (trong một DB): chia bảng theo khoảng thời gian hoặc theo key. Query có điều kiện trên partition key chỉ quét phần liên quan, xoá dữ liệu cũ bằng DROP PARTITION rất nhanh.
    • Sharding (nhiều DB): khi một máy không chịu nổi lượng ghi hoặc dung lượng. Đổi lại phải chọn shard key cẩn thận, query xuyên shard và transaction phân tán rất khó.

    Thứ tự hợp lý: tối ưu query và index, archive dữ liệu cũ, thêm replica và cache, partition, cuối cùng mới shard.

    Hay sai: chọn shard key gây hot spot, vd. theo ngày tạo khiến mọi lượt ghi dồn vào một shard.

    Ôn thêm câu hỏi SQL & Database →
  9. 09Virtual 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

    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 Semaphore nếu cần.
    • Trên Java 21, blocking bên trong synchronized có thể "pin" carrier; các bản JDK mới hơn đã cải thiện. Cẩn thận với ThreadLocal chứ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.

    Ôn thêm câu hỏi Java →
  10. 10Bạn làm việc thế nào khi áp lực cao hoặc deadline gấp?Câu hỏi hành vi & văn hoá

    Gợi ý trả lời

    Cho thấy bạn có cách làm cụ thể, không chỉ nói "em chịu được áp lực".

    • Chia nhỏ việc, ưu tiên phần quan trọng nhất cho mục tiêu.
    • Báo sớm cho lead/PM nếu thấy không kịp, đề xuất cắt phạm vi hoặc xin hỗ trợ.
    • Giữ chất lượng ở phần cốt lõi; ghi lại nợ kỹ thuật để xử lý sau.
    • Giữ bình tĩnh, giao tiếp ngắn gọn, rõ ràng với team.

    Câu mẫu theo STAR: "Trước buổi demo cho khách, team phát hiện lỗi tích hợp chỉ còn hai ngày. Em liệt kê các phần bị ảnh hưởng, cùng PM chọn luồng nào bắt buộc phải chạy cho demo, phần còn lại hẹn bàn giao tuần sau. Demo diễn ra suôn sẻ và khách đồng ý với lịch mới."

    Hay sai: khoe thức trắng nhiều đêm. Người phỏng vấn muốn thấy bạn quản lý được áp lực, không chỉ chịu đựng.

    Ôn thêm câu hỏi Câu hỏi hành vi & văn hoá →

Bạn đã phỏng vấn ở VPBank?

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