# UPDATE\_MYSQL

```sql
UPDATE users SET age = 30 WHERE id = 1;
```

MySQL (InnoDB engine) không chỉ đơn giản là “sửa dữ liệu”, mà sẽ thực hiện một loạt các bước rất kỹ lưỡng để đảm bảo **an toàn, hiệu suất, và nhất quán dữ liệu**, đặc biệt trong môi trường **transactional, concurrent**.

***

### 🔬 Quá trình thực thi câu lệnh `UPDATE` trong MySQL (InnoDB)

#### 📌 1. **Parser & Optimizer**

* SQL Parser phân tích cú pháp câu lệnh.
* Optimizer chọn **kế hoạch truy vấn tốt nhất** (dùng chỉ mục nếu có trong `WHERE`).

***

#### 📌 2. **Locking & MVCC**

* InnoDB lấy **row-level locks** cho các bản ghi phù hợp với `WHERE`.
* Dựa trên Isolation Level, MVCC sẽ đảm bảo dữ liệu đọc thấy là hợp lệ:
  * `REPEATABLE READ`: đọc snapshot cũ.
  * `READ COMMITTED`: đọc dữ liệu đã commit mới nhất.

***

#### 📌 3. **Ghi dữ liệu mới**

* InnoDB **không ghi đè row cũ**, mà:
  * Ghi **một bản sao mới** của row với `age = 30`.
  * Gắn các metadata như `trx_id`, `roll_pointer` (phục vụ rollback, MVCC).
* Row cũ vẫn được giữ lại trong **undo log**.

***

#### 📌 4. **Undo Log (Rollback Segment)**

* Ghi bản ghi cũ của row (trước khi update) vào **undo log**.
* Nếu transaction rollback, MySQL dùng undo log để **phục hồi lại giá trị cũ**.

***

#### 📌 5. **Change Buffer & Doublewrite Buffer**

* Nếu row không được truy cập thường xuyên, thay vì ghi trực tiếp vào disk, InnoDB ghi vào **change buffer** để tối ưu I/O.
* Ghi đồng thời vào **doublewrite buffer** (chống mất dữ liệu nếu crash khi đang ghi disk).

***

#### 📌 6. **Redo Log (WAL - Write Ahead Logging)**

* Ghi thông tin thay đổi vào **redo log (ib\_logfile)** để đảm bảo crash recovery.
* Ghi **trước khi ghi thật vào disk** (quy tắc Write Ahead Logging).

***

#### 📌 7. **Commit / Rollback**

* Khi gọi `COMMIT`, InnoDB sẽ:
  * Flush redo log.
  * Ghi transaction vào **binary log** (phục vụ replication).
  * Đánh dấu transaction là hoàn tất.
* Nếu `ROLLBACK`, dùng `undo log` để phục hồi lại row gốc.

***

### 🔁 Tóm tắt bằng flow

```
UPDATE
  → Parse + Optimize
    → Tìm row cần sửa (dùng index nếu có)
      → Lấy row-level lock
        → Ghi undo log
          → Ghi bản mới vào memory buffer
            → Ghi redo log (WAL)
              → COMMIT = flush + binlog + mark trx done
```

***

### ✅ Tối ưu UPDATE như một Senior

1. **WHERE có index** → tránh full table scan
2. **UPDATE theo batch nhỏ** nếu table lớn (`LIMIT`, `ORDER BY`)
3. **Tránh update primary key** → gây fragmentation
4. **Chỉ update khi thực sự cần** (sử dụng trigger, audit log)
5. **Xem lại Isolation level** → ảnh hưởng performance concurrency

***
