> For the complete documentation index, see [llms.txt](https://shniu.gitbook.io/cs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://shniu.gitbook.io/cs/middleware/mysql/mysql-transaction.md).

# MySQL Transaction

### 事务原子性

### 事务隔离 Isolation

#### MySQL 中锁设计的一般思想

* MySQL 中的锁 (InnoDB) 使用的是**两阶段锁协议**，也就是说锁是在需要的时候加上的，加锁后是在完成所有操作后一次性释放的

#### 事务的一般问题和事务隔离级别

多个事务之间并发操作，存在几个一般问题：脏读、不可重复读、幻读以及丢失更新，不同的隔离级别可以不同程度的解决这些问题。

* read committed 和 read uncommitted 隔离级别下或 RR 隔离级别下 `innodb_locks_unsafe_for_binlog` 设置为 `ON` 时，禁止`binlog_format=statement` ，详细分析和案例参考这里：[MySQL · 特性分析 · InnoDB对binlog\_format的限制](http://mysql.taobao.org/monthly/2018/08/04/)，or [MySQL Bug 23051](https://bugs.mysql.com/bug.php?id=23051)

主要原因是在主从复制时，会引起主从数据不一致，statement 记录的的是执行语句，不同事务执行语句的顺序会严重影响在备库数据还原的状态。本质的原因是RC级别并不满足事务串行化执行要求，没有解决不可重复读和幻读。

#### 幻读与Next-Key Locking

产生幻读的原因是，行锁只能锁住行，但新插入记录这个动作，要更新的是记录之间的“间隙”。因此，为了解决幻读问题，InnoDB 引入了新的锁，也就是间隙锁 (Gap Lock)；间隙锁，锁的就是两个值之间的空隙

数据行是可以加上锁的实体，数据行之间的间隙，也是可以加上锁的实体；

行锁分读锁和写锁，读锁之间可以兼容，读写锁和写写锁都是互斥的，也就是说行锁之间是相互影响的；但是间隙锁不一样，跟间隙锁存在冲突关系的，是“往这个间隙中插入一个记录”这个操作。

几个注意点

1. 间隙锁在可重复读隔离级别下才有效
2. MySQL 中细粒度的锁有行锁、间隙锁、Next-Key Lock
3. 一行数据可以加锁，数据之间的空隙也可以加锁，但是间隙锁之间不互斥，而是和插入数据这个操作互斥，也就是说加了间隙锁之后，往这个间隙中插入数据会被阻塞，直到间隙锁被释放了
4. 锁是加在索引上的
5. 如果用到覆盖索引，lock in share mode 只锁覆盖索引；for update 时，系统会认为接下来要更新数据，因此会顺便给主键索引上满足条件的行加上行锁；也就是说：**如果要用 lock in share mode 来给行加读锁避免数据被更新的话，就必须得绕过覆盖索引的优化，在查询字段中加入索引中不存在的字段**。
6.

加锁规则：

1. 加锁的基本单位是 next-key lock, next-key lock 是前开后闭的区间
2. 查找过程中访问到的对象才会加锁
3. 索引上的等值查询，给唯一索引加锁的时候，next-key lock 退化为行锁
4. 索引上的等值查询，向右遍历时且最后一个值不满足等值条件的时候，next-key lock 退化为间隙锁
5. 唯一索引上的范围查询会访问到不满足条件的第一个值为止

一些优化结论：

1. 在删除数据的时候尽量加 limit, 不仅可以控制删除数据的条数，让操作更安全，还可以减小加锁的范围

#### 事务锁类型

* 行锁

MySQL 的行锁有：行锁 (LOCK\_REC\_NOT\_GAP)、间隙锁(LOCK\_GAP)、Next-Key Lock

### 事务持久性

### 事务一致性


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://shniu.gitbook.io/cs/middleware/mysql/mysql-transaction.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
