MySQL 事务:一文把 ACID、隔离级别、MVCC、锁全串起来

MySQL 事务:从一笔转账说起,一文把 ACID、隔离级别、MVCC、锁全串起来

想象一个再平常不过的场景:你给朋友转 100 块钱。

在数据库里,这件事要分成两步------你的账户扣 100,朋友的账户加 100

可如果刚扣完你的钱,数据库突然宕机了,朋友那边没加上,这 100 块钱去哪了?凭空蒸发了?

再比如,转账过程中,恰好有人同时查你的余额------他会不会看到「扣了钱但还没加钱」的中间状态,以为你账户出了问题?

这些问题,全都要靠一个词来兜底:事务(Transaction)


一、什么是事务?从一笔转账说起

事务,就是「一组操作,要么全部成功,要么全部失败」的保证。

回到转账的例子,这两步必须被绑在一起:
#mermaid-svg-4v1xGaRS6hYAscrT{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-4v1xGaRS6hYAscrT .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-4v1xGaRS6hYAscrT .error-icon{fill:#552222;}#mermaid-svg-4v1xGaRS6hYAscrT .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-4v1xGaRS6hYAscrT .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-4v1xGaRS6hYAscrT .marker{fill:#333333;stroke:#333333;}#mermaid-svg-4v1xGaRS6hYAscrT .marker.cross{stroke:#333333;}#mermaid-svg-4v1xGaRS6hYAscrT svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-4v1xGaRS6hYAscrT p{margin:0;}#mermaid-svg-4v1xGaRS6hYAscrT .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-4v1xGaRS6hYAscrT .cluster-label text{fill:#333;}#mermaid-svg-4v1xGaRS6hYAscrT .cluster-label span{color:#333;}#mermaid-svg-4v1xGaRS6hYAscrT .cluster-label span p{background-color:transparent;}#mermaid-svg-4v1xGaRS6hYAscrT .label text,#mermaid-svg-4v1xGaRS6hYAscrT span{fill:#333;color:#333;}#mermaid-svg-4v1xGaRS6hYAscrT .node rect,#mermaid-svg-4v1xGaRS6hYAscrT .node circle,#mermaid-svg-4v1xGaRS6hYAscrT .node ellipse,#mermaid-svg-4v1xGaRS6hYAscrT .node polygon,#mermaid-svg-4v1xGaRS6hYAscrT .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-4v1xGaRS6hYAscrT .rough-node .label text,#mermaid-svg-4v1xGaRS6hYAscrT .node .label text,#mermaid-svg-4v1xGaRS6hYAscrT .image-shape .label,#mermaid-svg-4v1xGaRS6hYAscrT .icon-shape .label{text-anchor:middle;}#mermaid-svg-4v1xGaRS6hYAscrT .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-4v1xGaRS6hYAscrT .rough-node .label,#mermaid-svg-4v1xGaRS6hYAscrT .node .label,#mermaid-svg-4v1xGaRS6hYAscrT .image-shape .label,#mermaid-svg-4v1xGaRS6hYAscrT .icon-shape .label{text-align:center;}#mermaid-svg-4v1xGaRS6hYAscrT .node.clickable{cursor:pointer;}#mermaid-svg-4v1xGaRS6hYAscrT .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-4v1xGaRS6hYAscrT .arrowheadPath{fill:#333333;}#mermaid-svg-4v1xGaRS6hYAscrT .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-4v1xGaRS6hYAscrT .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-4v1xGaRS6hYAscrT .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4v1xGaRS6hYAscrT .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-4v1xGaRS6hYAscrT .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4v1xGaRS6hYAscrT .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-4v1xGaRS6hYAscrT .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-4v1xGaRS6hYAscrT .cluster text{fill:#333;}#mermaid-svg-4v1xGaRS6hYAscrT .cluster span{color:#333;}#mermaid-svg-4v1xGaRS6hYAscrT div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-4v1xGaRS6hYAscrT .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-4v1xGaRS6hYAscrT rect.text{fill:none;stroke-width:0;}#mermaid-svg-4v1xGaRS6hYAscrT .icon-shape,#mermaid-svg-4v1xGaRS6hYAscrT .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-4v1xGaRS6hYAscrT .icon-shape p,#mermaid-svg-4v1xGaRS6hYAscrT .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-4v1xGaRS6hYAscrT .icon-shape .label rect,#mermaid-svg-4v1xGaRS6hYAscrT .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-4v1xGaRS6hYAscrT .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-4v1xGaRS6hYAscrT .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-4v1xGaRS6hYAscrT :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 是

开始事务
① 你的账户 -100
② 朋友的账户 +100
都成功了?
提交(Commit)

两个改动都生效
回滚(Rollback)

两个改动都撤销

如果没有事务,第一步成功、第二步失败,钱就丢了;有了事务,要么「扣了也加了」,要么「都回滚,就当没发生过」。

一句话 :事务把一堆零散的 SQL,打包成一个「不可分割的整体」。要么一起成,要么一起亡。

在 MySQL 里,事务是由「存储引擎」提供的。只有 InnoDB 引擎支持完整的事务(这也是现在默认用 InnoDB 的重要原因),老旧的 MyISAM 是不支持事务的。


二、ACID:事务的四大特性

事务之所以可靠,靠的是四个特性,合称 ACID

特性 全称 通俗解释 生活类比
A Atomicity 原子性 要么全做,要么全不做 转账:扣钱和加钱绑死
C Consistency 一致性 事务前后,数据都符合规则 钱的总数始终不变
I Isolation 隔离性 事务之间互不干扰 别人看不到你改到一半
D Durability 持久性 提交后永久保存,不丢 钱到账了就是到账了

#mermaid-svg-yRVLGEe8aGWy68UL{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-yRVLGEe8aGWy68UL .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-yRVLGEe8aGWy68UL .error-icon{fill:#552222;}#mermaid-svg-yRVLGEe8aGWy68UL .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-yRVLGEe8aGWy68UL .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-yRVLGEe8aGWy68UL .marker{fill:#333333;stroke:#333333;}#mermaid-svg-yRVLGEe8aGWy68UL .marker.cross{stroke:#333333;}#mermaid-svg-yRVLGEe8aGWy68UL svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-yRVLGEe8aGWy68UL p{margin:0;}#mermaid-svg-yRVLGEe8aGWy68UL .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-yRVLGEe8aGWy68UL .cluster-label text{fill:#333;}#mermaid-svg-yRVLGEe8aGWy68UL .cluster-label span{color:#333;}#mermaid-svg-yRVLGEe8aGWy68UL .cluster-label span p{background-color:transparent;}#mermaid-svg-yRVLGEe8aGWy68UL .label text,#mermaid-svg-yRVLGEe8aGWy68UL span{fill:#333;color:#333;}#mermaid-svg-yRVLGEe8aGWy68UL .node rect,#mermaid-svg-yRVLGEe8aGWy68UL .node circle,#mermaid-svg-yRVLGEe8aGWy68UL .node ellipse,#mermaid-svg-yRVLGEe8aGWy68UL .node polygon,#mermaid-svg-yRVLGEe8aGWy68UL .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-yRVLGEe8aGWy68UL .rough-node .label text,#mermaid-svg-yRVLGEe8aGWy68UL .node .label text,#mermaid-svg-yRVLGEe8aGWy68UL .image-shape .label,#mermaid-svg-yRVLGEe8aGWy68UL .icon-shape .label{text-anchor:middle;}#mermaid-svg-yRVLGEe8aGWy68UL .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-yRVLGEe8aGWy68UL .rough-node .label,#mermaid-svg-yRVLGEe8aGWy68UL .node .label,#mermaid-svg-yRVLGEe8aGWy68UL .image-shape .label,#mermaid-svg-yRVLGEe8aGWy68UL .icon-shape .label{text-align:center;}#mermaid-svg-yRVLGEe8aGWy68UL .node.clickable{cursor:pointer;}#mermaid-svg-yRVLGEe8aGWy68UL .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-yRVLGEe8aGWy68UL .arrowheadPath{fill:#333333;}#mermaid-svg-yRVLGEe8aGWy68UL .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-yRVLGEe8aGWy68UL .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-yRVLGEe8aGWy68UL .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yRVLGEe8aGWy68UL .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-yRVLGEe8aGWy68UL .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yRVLGEe8aGWy68UL .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-yRVLGEe8aGWy68UL .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-yRVLGEe8aGWy68UL .cluster text{fill:#333;}#mermaid-svg-yRVLGEe8aGWy68UL .cluster span{color:#333;}#mermaid-svg-yRVLGEe8aGWy68UL div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-yRVLGEe8aGWy68UL .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-yRVLGEe8aGWy68UL rect.text{fill:none;stroke-width:0;}#mermaid-svg-yRVLGEe8aGWy68UL .icon-shape,#mermaid-svg-yRVLGEe8aGWy68UL .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-yRVLGEe8aGWy68UL .icon-shape p,#mermaid-svg-yRVLGEe8aGWy68UL .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-yRVLGEe8aGWy68UL .icon-shape .label rect,#mermaid-svg-yRVLGEe8aGWy68UL .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-yRVLGEe8aGWy68UL .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-yRVLGEe8aGWy68UL .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-yRVLGEe8aGWy68UL :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 靠回滚保证
靠锁 + MVCC
靠重做日志
ACID 四大特性
原子性

Atomicity
一致性

Consistency
隔离性

Isolation
持久性

Durability
undo log
锁 / MVCC
redo log

一句话 :ACID 四兄弟里,原子性靠回滚日志(undo log)兜底,持久性靠重做日志(redo log)兜底,隔离性靠锁和 MVCC 兜底


三、没有隔离会怎样?三大并发问题

事务之间的「隔离性」如果做不好,就会出现三个经典的并发问题。搞懂它们,是理解隔离级别的前提。

假设有两个事务同时操作同一行数据:

3.1 脏读(Dirty Read)

读到了别人「还没提交」的、可能回滚的脏数据。
事务 B 事务 A 事务 B 事务 A #mermaid-svg-fQpfBj2A8Eq56Cmo{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-fQpfBj2A8Eq56Cmo .error-icon{fill:#552222;}#mermaid-svg-fQpfBj2A8Eq56Cmo .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-fQpfBj2A8Eq56Cmo .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-fQpfBj2A8Eq56Cmo .marker{fill:#333333;stroke:#333333;}#mermaid-svg-fQpfBj2A8Eq56Cmo .marker.cross{stroke:#333333;}#mermaid-svg-fQpfBj2A8Eq56Cmo svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-fQpfBj2A8Eq56Cmo p{margin:0;}#mermaid-svg-fQpfBj2A8Eq56Cmo .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-fQpfBj2A8Eq56Cmo text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-fQpfBj2A8Eq56Cmo .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-fQpfBj2A8Eq56Cmo .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-fQpfBj2A8Eq56Cmo #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-fQpfBj2A8Eq56Cmo .sequenceNumber{fill:white;}#mermaid-svg-fQpfBj2A8Eq56Cmo #sequencenumber{fill:#333;}#mermaid-svg-fQpfBj2A8Eq56Cmo #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-fQpfBj2A8Eq56Cmo .messageText{fill:#333;stroke:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-fQpfBj2A8Eq56Cmo .labelText,#mermaid-svg-fQpfBj2A8Eq56Cmo .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .loopText,#mermaid-svg-fQpfBj2A8Eq56Cmo .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-fQpfBj2A8Eq56Cmo .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-fQpfBj2A8Eq56Cmo .noteText,#mermaid-svg-fQpfBj2A8Eq56Cmo .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-fQpfBj2A8Eq56Cmo .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-fQpfBj2A8Eq56Cmo .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-fQpfBj2A8Eq56Cmo .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-fQpfBj2A8Eq56Cmo .actorPopupMenu{position:absolute;}#mermaid-svg-fQpfBj2A8Eq56Cmo .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-fQpfBj2A8Eq56Cmo .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-fQpfBj2A8Eq56Cmo .actor-man circle,#mermaid-svg-fQpfBj2A8Eq56Cmo line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-fQpfBj2A8Eq56Cmo :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} B 读到的是「脏数据」那 500 根本不存在 余额改为 500(未提交)读到余额 = 500回滚,余额回到 100

3.2 不可重复读(Non-Repeatable Read)

同一事务内,两次读同一行,结果不一样(因为别人在中间提交了修改)。
事务 B 事务 A 事务 B 事务 A #mermaid-svg-26AlUzIRUyHesZWu{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-26AlUzIRUyHesZWu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-26AlUzIRUyHesZWu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-26AlUzIRUyHesZWu .error-icon{fill:#552222;}#mermaid-svg-26AlUzIRUyHesZWu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-26AlUzIRUyHesZWu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-26AlUzIRUyHesZWu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-26AlUzIRUyHesZWu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-26AlUzIRUyHesZWu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-26AlUzIRUyHesZWu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-26AlUzIRUyHesZWu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-26AlUzIRUyHesZWu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-26AlUzIRUyHesZWu .marker.cross{stroke:#333333;}#mermaid-svg-26AlUzIRUyHesZWu svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-26AlUzIRUyHesZWu p{margin:0;}#mermaid-svg-26AlUzIRUyHesZWu .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-26AlUzIRUyHesZWu text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-26AlUzIRUyHesZWu .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-26AlUzIRUyHesZWu .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-26AlUzIRUyHesZWu .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-26AlUzIRUyHesZWu .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-26AlUzIRUyHesZWu #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-26AlUzIRUyHesZWu .sequenceNumber{fill:white;}#mermaid-svg-26AlUzIRUyHesZWu #sequencenumber{fill:#333;}#mermaid-svg-26AlUzIRUyHesZWu #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-26AlUzIRUyHesZWu .messageText{fill:#333;stroke:none;}#mermaid-svg-26AlUzIRUyHesZWu .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-26AlUzIRUyHesZWu .labelText,#mermaid-svg-26AlUzIRUyHesZWu .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-26AlUzIRUyHesZWu .loopText,#mermaid-svg-26AlUzIRUyHesZWu .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-26AlUzIRUyHesZWu .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-26AlUzIRUyHesZWu .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-26AlUzIRUyHesZWu .noteText,#mermaid-svg-26AlUzIRUyHesZWu .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-26AlUzIRUyHesZWu .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-26AlUzIRUyHesZWu .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-26AlUzIRUyHesZWu .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-26AlUzIRUyHesZWu .actorPopupMenu{position:absolute;}#mermaid-svg-26AlUzIRUyHesZWu .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-26AlUzIRUyHesZWu .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-26AlUzIRUyHesZWu .actor-man circle,#mermaid-svg-26AlUzIRUyHesZWu line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-26AlUzIRUyHesZWu :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 两次读不一样,「重复读」失败 第一次读余额 = 100把余额改成 500 并提交第二次读余额 = 500

3.3 幻读(Phantom Read)

同一事务内,两次查询「符合条件的行数」不一样(因为别人在中间插入了新数据)。
事务 B 事务 A 事务 B 事务 A #mermaid-svg-HV0KSpm1pTlRQcyN{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-HV0KSpm1pTlRQcyN .error-icon{fill:#552222;}#mermaid-svg-HV0KSpm1pTlRQcyN .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-HV0KSpm1pTlRQcyN .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-HV0KSpm1pTlRQcyN .marker{fill:#333333;stroke:#333333;}#mermaid-svg-HV0KSpm1pTlRQcyN .marker.cross{stroke:#333333;}#mermaid-svg-HV0KSpm1pTlRQcyN svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-HV0KSpm1pTlRQcyN p{margin:0;}#mermaid-svg-HV0KSpm1pTlRQcyN .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HV0KSpm1pTlRQcyN text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HV0KSpm1pTlRQcyN .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-HV0KSpm1pTlRQcyN .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-HV0KSpm1pTlRQcyN #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-HV0KSpm1pTlRQcyN .sequenceNumber{fill:white;}#mermaid-svg-HV0KSpm1pTlRQcyN #sequencenumber{fill:#333;}#mermaid-svg-HV0KSpm1pTlRQcyN #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-HV0KSpm1pTlRQcyN .messageText{fill:#333;stroke:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HV0KSpm1pTlRQcyN .labelText,#mermaid-svg-HV0KSpm1pTlRQcyN .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .loopText,#mermaid-svg-HV0KSpm1pTlRQcyN .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-HV0KSpm1pTlRQcyN .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-HV0KSpm1pTlRQcyN .noteText,#mermaid-svg-HV0KSpm1pTlRQcyN .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-HV0KSpm1pTlRQcyN .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HV0KSpm1pTlRQcyN .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HV0KSpm1pTlRQcyN .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-HV0KSpm1pTlRQcyN .actorPopupMenu{position:absolute;}#mermaid-svg-HV0KSpm1pTlRQcyN .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-HV0KSpm1pTlRQcyN .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-HV0KSpm1pTlRQcyN .actor-man circle,#mermaid-svg-HV0KSpm1pTlRQcyN line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-HV0KSpm1pTlRQcyN :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 多出来的那条,像「幻影」一样 查询:金额>100 的用户 → 3 条插入一条金额=200 的记录并提交再查:金额>100 的用户 → 4 条

一句话 :脏读是「读到了没提交的」,不可重复读是「同一行被改了」,幻读是「多出了新的行」。一个比一个更隐蔽,也一个比一个更难解决。


四、四大隔离级别:越严越安全,越严越慢

为了解决上面三个问题,SQL 标准定义了四个隔离级别(Isolation Level),从宽松到严格:
#mermaid-svg-PV9mwEG27pA2dBOH{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-PV9mwEG27pA2dBOH .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-PV9mwEG27pA2dBOH .error-icon{fill:#552222;}#mermaid-svg-PV9mwEG27pA2dBOH .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-PV9mwEG27pA2dBOH .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-PV9mwEG27pA2dBOH .marker{fill:#333333;stroke:#333333;}#mermaid-svg-PV9mwEG27pA2dBOH .marker.cross{stroke:#333333;}#mermaid-svg-PV9mwEG27pA2dBOH svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-PV9mwEG27pA2dBOH p{margin:0;}#mermaid-svg-PV9mwEG27pA2dBOH .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-PV9mwEG27pA2dBOH .cluster-label text{fill:#333;}#mermaid-svg-PV9mwEG27pA2dBOH .cluster-label span{color:#333;}#mermaid-svg-PV9mwEG27pA2dBOH .cluster-label span p{background-color:transparent;}#mermaid-svg-PV9mwEG27pA2dBOH .label text,#mermaid-svg-PV9mwEG27pA2dBOH span{fill:#333;color:#333;}#mermaid-svg-PV9mwEG27pA2dBOH .node rect,#mermaid-svg-PV9mwEG27pA2dBOH .node circle,#mermaid-svg-PV9mwEG27pA2dBOH .node ellipse,#mermaid-svg-PV9mwEG27pA2dBOH .node polygon,#mermaid-svg-PV9mwEG27pA2dBOH .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-PV9mwEG27pA2dBOH .rough-node .label text,#mermaid-svg-PV9mwEG27pA2dBOH .node .label text,#mermaid-svg-PV9mwEG27pA2dBOH .image-shape .label,#mermaid-svg-PV9mwEG27pA2dBOH .icon-shape .label{text-anchor:middle;}#mermaid-svg-PV9mwEG27pA2dBOH .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-PV9mwEG27pA2dBOH .rough-node .label,#mermaid-svg-PV9mwEG27pA2dBOH .node .label,#mermaid-svg-PV9mwEG27pA2dBOH .image-shape .label,#mermaid-svg-PV9mwEG27pA2dBOH .icon-shape .label{text-align:center;}#mermaid-svg-PV9mwEG27pA2dBOH .node.clickable{cursor:pointer;}#mermaid-svg-PV9mwEG27pA2dBOH .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-PV9mwEG27pA2dBOH .arrowheadPath{fill:#333333;}#mermaid-svg-PV9mwEG27pA2dBOH .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-PV9mwEG27pA2dBOH .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-PV9mwEG27pA2dBOH .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PV9mwEG27pA2dBOH .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-PV9mwEG27pA2dBOH .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PV9mwEG27pA2dBOH .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-PV9mwEG27pA2dBOH .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-PV9mwEG27pA2dBOH .cluster text{fill:#333;}#mermaid-svg-PV9mwEG27pA2dBOH .cluster span{color:#333;}#mermaid-svg-PV9mwEG27pA2dBOH div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-PV9mwEG27pA2dBOH .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-PV9mwEG27pA2dBOH rect.text{fill:none;stroke-width:0;}#mermaid-svg-PV9mwEG27pA2dBOH .icon-shape,#mermaid-svg-PV9mwEG27pA2dBOH .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-PV9mwEG27pA2dBOH .icon-shape p,#mermaid-svg-PV9mwEG27pA2dBOH .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-PV9mwEG27pA2dBOH .icon-shape .label rect,#mermaid-svg-PV9mwEG27pA2dBOH .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-PV9mwEG27pA2dBOH .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-PV9mwEG27pA2dBOH .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-PV9mwEG27pA2dBOH :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 读未提交

Read Uncommitted
读已提交

Read Committed
可重复读

Repeatable Read
串行化

Serializable

隔离级别 脏读 不可重复读 幻读 并发性能
读未提交 ❌ 会发生 ❌ 会发生 ❌ 会发生 最高
读已提交 ✅ 解决 ❌ 会发生 ❌ 会发生 较高
可重复读(MySQL 默认) ✅ 解决 ✅ 解决 ⚠️ 大部分解决 中等
串行化 ✅ 解决 ✅ 解决 ✅ 解决 最低

几个关键点要记住:

  • MySQL 默认是「可重复读(Repeatable Read)」,这和很多教材写的「默认读已提交」不一样(那是 Oracle 等数据库);
  • 「可重复读」在 InnoDB 里,通过 MVCC + 间隙锁,幻读也基本被解决了,所以实际表现比理论表格更强;
  • 级别越高越安全,但并发越差、锁越多、越慢。不是越严越好,要按业务选。
text 复制代码
-- 查看当前隔离级别
SELECT @@transaction_isolation;

-- 设置隔离级别(会话级)
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

五、MVCC:读不阻塞写的秘密

你可能会疑惑:MySQL 默认「可重复读」,那它是怎么做到「我读的时候,别人还能同时写」的?答案是一个很精妙的设计------MVCC(多版本并发控制)

5.1 核心思想

MVCC 的核心就一句话:读操作不直接读「正在被改的那份数据」,而是读「历史快照」

它不给数据「上锁」,而是给每行数据保留多个版本
#mermaid-svg-jqHKbSrZ3uaYAFr9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .error-icon{fill:#552222;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .marker.cross{stroke:#333333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 p{margin:0;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster-label text{fill:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster-label span{color:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster-label span p{background-color:transparent;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .label text,#mermaid-svg-jqHKbSrZ3uaYAFr9 span{fill:#333;color:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .node rect,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node circle,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node ellipse,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node polygon,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .rough-node .label text,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node .label text,#mermaid-svg-jqHKbSrZ3uaYAFr9 .image-shape .label,#mermaid-svg-jqHKbSrZ3uaYAFr9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .rough-node .label,#mermaid-svg-jqHKbSrZ3uaYAFr9 .node .label,#mermaid-svg-jqHKbSrZ3uaYAFr9 .image-shape .label,#mermaid-svg-jqHKbSrZ3uaYAFr9 .icon-shape .label{text-align:center;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .node.clickable{cursor:pointer;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .arrowheadPath{fill:#333333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-jqHKbSrZ3uaYAFr9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jqHKbSrZ3uaYAFr9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster text{fill:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .cluster span{color:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-jqHKbSrZ3uaYAFr9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .icon-shape,#mermaid-svg-jqHKbSrZ3uaYAFr9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .icon-shape p,#mermaid-svg-jqHKbSrZ3uaYAFr9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .icon-shape .label rect,#mermaid-svg-jqHKbSrZ3uaYAFr9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-jqHKbSrZ3uaYAFr9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-jqHKbSrZ3uaYAFr9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-jqHKbSrZ3uaYAFr9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 读快照 → 拿到 100
写新版本
互不阻塞
一行数据
版本 1

(旧值 100)
版本 2

(新值 500,未提交)
事务 A 读
事务 B 写

  • 写事务:不改旧数据,而是新建一个「新版本」;
  • 读事务:根据自己开启时的「快照」,读到自己该看到的那个版本。

这样,读和写互不阻塞,大大提升了并发能力。

5.2 快照是怎么实现的?

MVCC 的实现,靠两个隐藏字段 + 一个日志:

机制 作用
隐藏字段(事务 ID、回滚指针) 标记每一行的版本信息
undo log(回滚日志) 保存历史版本,供快照读取和回滚

#mermaid-svg-0dYVSNKlmMZ3p6Wt{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .error-icon{fill:#552222;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .marker.cross{stroke:#333333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt p{margin:0;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster-label text{fill:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster-label span{color:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster-label span p{background-color:transparent;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .label text,#mermaid-svg-0dYVSNKlmMZ3p6Wt span{fill:#333;color:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .node rect,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node circle,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node ellipse,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node polygon,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .rough-node .label text,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node .label text,#mermaid-svg-0dYVSNKlmMZ3p6Wt .image-shape .label,#mermaid-svg-0dYVSNKlmMZ3p6Wt .icon-shape .label{text-anchor:middle;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .rough-node .label,#mermaid-svg-0dYVSNKlmMZ3p6Wt .node .label,#mermaid-svg-0dYVSNKlmMZ3p6Wt .image-shape .label,#mermaid-svg-0dYVSNKlmMZ3p6Wt .icon-shape .label{text-align:center;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .node.clickable{cursor:pointer;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .arrowheadPath{fill:#333333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-0dYVSNKlmMZ3p6Wt .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0dYVSNKlmMZ3p6Wt .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster text{fill:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .cluster span{color:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-0dYVSNKlmMZ3p6Wt rect.text{fill:none;stroke-width:0;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .icon-shape,#mermaid-svg-0dYVSNKlmMZ3p6Wt .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .icon-shape p,#mermaid-svg-0dYVSNKlmMZ3p6Wt .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .icon-shape .label rect,#mermaid-svg-0dYVSNKlmMZ3p6Wt .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-0dYVSNKlmMZ3p6Wt .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-0dYVSNKlmMZ3p6Wt .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-0dYVSNKlmMZ3p6Wt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 回滚指针
回滚指针
当前版本

(余额=500,事务 ID=200)
历史版本

(余额=100,事务 ID=100)
更早版本

(余额=80)

通过这条「版本链」,一个事务就能在「当前值 500」的前提下,依然读到自己快照对应的「历史值 100」。

一句话 :MVCC 的本质是「用空间换并发」------多存几个历史版本,让读操作永远有「过去的版本」可读,从而不用和写操作抢锁。这也是「可重复读」能既安全又不太慢的根本原因。


六、锁:事务的物理防线

MVCC 解决了「读」,但「写」之间还是会冲突的------两个事务不能同时改同一行。这时候,就轮到**锁(Lock)**上场了。

6.1 按范围分:表锁 vs 行锁

锁类型 锁住什么 特点
表锁 整张表 简单粗暴,并发差
行锁 某几行 粒度细,并发好(InnoDB 默认)

InnoDB 用的是行锁,所以高并发场景下性能更好。

6.2 按模式分:共享锁 vs 排他锁

锁模式 简称 能干什么 谁和谁互斥
共享锁 S 锁 和排他锁互斥,和共享锁兼容
排他锁 X 锁 和谁都互斥

6.3 死锁:两个事务互相等对方

锁的经典事故就是死锁
#mermaid-svg-cBfxHZr55RKTlPu1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-cBfxHZr55RKTlPu1 .error-icon{fill:#552222;}#mermaid-svg-cBfxHZr55RKTlPu1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-cBfxHZr55RKTlPu1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-cBfxHZr55RKTlPu1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-cBfxHZr55RKTlPu1 .marker.cross{stroke:#333333;}#mermaid-svg-cBfxHZr55RKTlPu1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-cBfxHZr55RKTlPu1 p{margin:0;}#mermaid-svg-cBfxHZr55RKTlPu1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster-label text{fill:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster-label span{color:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster-label span p{background-color:transparent;}#mermaid-svg-cBfxHZr55RKTlPu1 .label text,#mermaid-svg-cBfxHZr55RKTlPu1 span{fill:#333;color:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 .node rect,#mermaid-svg-cBfxHZr55RKTlPu1 .node circle,#mermaid-svg-cBfxHZr55RKTlPu1 .node ellipse,#mermaid-svg-cBfxHZr55RKTlPu1 .node polygon,#mermaid-svg-cBfxHZr55RKTlPu1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-cBfxHZr55RKTlPu1 .rough-node .label text,#mermaid-svg-cBfxHZr55RKTlPu1 .node .label text,#mermaid-svg-cBfxHZr55RKTlPu1 .image-shape .label,#mermaid-svg-cBfxHZr55RKTlPu1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-cBfxHZr55RKTlPu1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-cBfxHZr55RKTlPu1 .rough-node .label,#mermaid-svg-cBfxHZr55RKTlPu1 .node .label,#mermaid-svg-cBfxHZr55RKTlPu1 .image-shape .label,#mermaid-svg-cBfxHZr55RKTlPu1 .icon-shape .label{text-align:center;}#mermaid-svg-cBfxHZr55RKTlPu1 .node.clickable{cursor:pointer;}#mermaid-svg-cBfxHZr55RKTlPu1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-cBfxHZr55RKTlPu1 .arrowheadPath{fill:#333333;}#mermaid-svg-cBfxHZr55RKTlPu1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-cBfxHZr55RKTlPu1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-cBfxHZr55RKTlPu1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cBfxHZr55RKTlPu1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-cBfxHZr55RKTlPu1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cBfxHZr55RKTlPu1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster text{fill:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 .cluster span{color:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-cBfxHZr55RKTlPu1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-cBfxHZr55RKTlPu1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-cBfxHZr55RKTlPu1 .icon-shape,#mermaid-svg-cBfxHZr55RKTlPu1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-cBfxHZr55RKTlPu1 .icon-shape p,#mermaid-svg-cBfxHZr55RKTlPu1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-cBfxHZr55RKTlPu1 .icon-shape .label rect,#mermaid-svg-cBfxHZr55RKTlPu1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-cBfxHZr55RKTlPu1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-cBfxHZr55RKTlPu1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-cBfxHZr55RKTlPu1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 等待
等待
事务 A:

锁了 1 号行,等着 2 号行
事务 B:

锁了 2 号行,等着 1 号行

两个事务互相拿着对方要的锁,谁也不放,僵住了。MySQL 会自动检测死锁,强制回滚其中一个事务来破局。

一句话:MVCC 管「读」,锁管「写」。锁是事务的「物理防线」,但用不好就会造成阻塞和死锁------这也是「为什么数据库有时会莫名其妙卡住」的根源。


七、事务的传播行为(Spring 里的事)

我们实际写代码,大多通过 Spring 的 @Transactional 来用事务。这里有个概念特别容易搞混,但必须懂:事务的传播行为(Propagation)

它回答的问题是:一个事务方法,调用了另一个事务方法,这俩事务是什么关系?
#mermaid-svg-iPje2V6KHpP9tS0q{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-iPje2V6KHpP9tS0q .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-iPje2V6KHpP9tS0q .error-icon{fill:#552222;}#mermaid-svg-iPje2V6KHpP9tS0q .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-iPje2V6KHpP9tS0q .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-iPje2V6KHpP9tS0q .marker{fill:#333333;stroke:#333333;}#mermaid-svg-iPje2V6KHpP9tS0q .marker.cross{stroke:#333333;}#mermaid-svg-iPje2V6KHpP9tS0q svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-iPje2V6KHpP9tS0q p{margin:0;}#mermaid-svg-iPje2V6KHpP9tS0q .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-iPje2V6KHpP9tS0q .cluster-label text{fill:#333;}#mermaid-svg-iPje2V6KHpP9tS0q .cluster-label span{color:#333;}#mermaid-svg-iPje2V6KHpP9tS0q .cluster-label span p{background-color:transparent;}#mermaid-svg-iPje2V6KHpP9tS0q .label text,#mermaid-svg-iPje2V6KHpP9tS0q span{fill:#333;color:#333;}#mermaid-svg-iPje2V6KHpP9tS0q .node rect,#mermaid-svg-iPje2V6KHpP9tS0q .node circle,#mermaid-svg-iPje2V6KHpP9tS0q .node ellipse,#mermaid-svg-iPje2V6KHpP9tS0q .node polygon,#mermaid-svg-iPje2V6KHpP9tS0q .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-iPje2V6KHpP9tS0q .rough-node .label text,#mermaid-svg-iPje2V6KHpP9tS0q .node .label text,#mermaid-svg-iPje2V6KHpP9tS0q .image-shape .label,#mermaid-svg-iPje2V6KHpP9tS0q .icon-shape .label{text-anchor:middle;}#mermaid-svg-iPje2V6KHpP9tS0q .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-iPje2V6KHpP9tS0q .rough-node .label,#mermaid-svg-iPje2V6KHpP9tS0q .node .label,#mermaid-svg-iPje2V6KHpP9tS0q .image-shape .label,#mermaid-svg-iPje2V6KHpP9tS0q .icon-shape .label{text-align:center;}#mermaid-svg-iPje2V6KHpP9tS0q .node.clickable{cursor:pointer;}#mermaid-svg-iPje2V6KHpP9tS0q .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-iPje2V6KHpP9tS0q .arrowheadPath{fill:#333333;}#mermaid-svg-iPje2V6KHpP9tS0q .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-iPje2V6KHpP9tS0q .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-iPje2V6KHpP9tS0q .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iPje2V6KHpP9tS0q .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-iPje2V6KHpP9tS0q .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iPje2V6KHpP9tS0q .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-iPje2V6KHpP9tS0q .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-iPje2V6KHpP9tS0q .cluster text{fill:#333;}#mermaid-svg-iPje2V6KHpP9tS0q .cluster span{color:#333;}#mermaid-svg-iPje2V6KHpP9tS0q div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-iPje2V6KHpP9tS0q .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-iPje2V6KHpP9tS0q rect.text{fill:none;stroke-width:0;}#mermaid-svg-iPje2V6KHpP9tS0q .icon-shape,#mermaid-svg-iPje2V6KHpP9tS0q .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-iPje2V6KHpP9tS0q .icon-shape p,#mermaid-svg-iPje2V6KHpP9tS0q .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-iPje2V6KHpP9tS0q .icon-shape .label rect,#mermaid-svg-iPje2V6KHpP9tS0q .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-iPje2V6KHpP9tS0q .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-iPje2V6KHpP9tS0q .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-iPje2V6KHpP9tS0q :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 调用
方法 A(有事务)
方法 B(也有事务)
B 该用哪个事务?
用 A 的事务(一起提交)
新开一个事务(各管各)
不用事务

常见的几种传播行为:

传播行为 含义 通俗说法
REQUIRED(默认) 有就用,没有就新建 「随大流」
REQUIRES_NEW 总是新开一个独立事务 「另起炉灶」
SUPPORTS 有就加入,没有就算了 「随缘」
NOT_SUPPORTED 挂起当前事务,自己不用事务跑 「暂时脱离」
MANDATORY 必须已有事务,否则报错 「必须有人带着」
NEVER 必须没有事务,否则报错 「绝不沾事务」

一句话 :传播行为解决的是「多个事务方法嵌套时,事务到底听谁的」。默认的 REQUIRED 会「加入已有事务」,这也是「为什么内层方法异常会连累外层一起回滚」的原因。


八、事务失效的常见坑(重点避雷)

@Transactional 看起来简单,但失效的场景多到离谱。这里发散地列出最常踩的几个,都是生产血泪:

为什么失效 解法
同类内部调用 自己调自己,绕过了代理 拆到不同类,或注入自己
方法不是 public Spring 只能代理 public 方法 改成 public
异常被 catch 吞掉 事务感知不到异常,以为没出错 手动 rollback 或抛出
抛的是受检异常 默认只对 RuntimeException 回滚 指定 rollbackFor
类没被 Spring 管理 自己 new 的,不是 Bean 交给容器管理
数据库不支持事务 用了 MyISAM 等引擎 换成 InnoDB

其中「异常被吞掉」最隐蔽:

java 复制代码
@Transactional
public void save() {
    try {
        dao.insert();        // 这里抛了异常
    } catch (Exception e) {
        log.error("出错", e);   // 被 catch 吞掉了,没往外抛
        // 事务不知道出错了 → 不会回滚!
    }
}

一句话 :事务失效,99% 的原因都是「Spring 的代理机制没生效 」或「异常没让事务知道」。记住这两条主线,大部分坑都能一眼看穿。


九、大事务的危害与优化

事务不是越大越好。一个「大事务」------比如一个事务里塞了几万条数据、跑了几十秒------是很多性能问题的罪魁祸首。

9.1 大事务的危害

#mermaid-svg-JY0klfuDRD2oQEr8{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-JY0klfuDRD2oQEr8 .error-icon{fill:#552222;}#mermaid-svg-JY0klfuDRD2oQEr8 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-JY0klfuDRD2oQEr8 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-JY0klfuDRD2oQEr8 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-JY0klfuDRD2oQEr8 .marker.cross{stroke:#333333;}#mermaid-svg-JY0klfuDRD2oQEr8 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-JY0klfuDRD2oQEr8 p{margin:0;}#mermaid-svg-JY0klfuDRD2oQEr8 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster-label text{fill:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster-label span{color:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster-label span p{background-color:transparent;}#mermaid-svg-JY0klfuDRD2oQEr8 .label text,#mermaid-svg-JY0klfuDRD2oQEr8 span{fill:#333;color:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 .node rect,#mermaid-svg-JY0klfuDRD2oQEr8 .node circle,#mermaid-svg-JY0klfuDRD2oQEr8 .node ellipse,#mermaid-svg-JY0klfuDRD2oQEr8 .node polygon,#mermaid-svg-JY0klfuDRD2oQEr8 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-JY0klfuDRD2oQEr8 .rough-node .label text,#mermaid-svg-JY0klfuDRD2oQEr8 .node .label text,#mermaid-svg-JY0klfuDRD2oQEr8 .image-shape .label,#mermaid-svg-JY0klfuDRD2oQEr8 .icon-shape .label{text-anchor:middle;}#mermaid-svg-JY0klfuDRD2oQEr8 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-JY0klfuDRD2oQEr8 .rough-node .label,#mermaid-svg-JY0klfuDRD2oQEr8 .node .label,#mermaid-svg-JY0klfuDRD2oQEr8 .image-shape .label,#mermaid-svg-JY0klfuDRD2oQEr8 .icon-shape .label{text-align:center;}#mermaid-svg-JY0klfuDRD2oQEr8 .node.clickable{cursor:pointer;}#mermaid-svg-JY0klfuDRD2oQEr8 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-JY0klfuDRD2oQEr8 .arrowheadPath{fill:#333333;}#mermaid-svg-JY0klfuDRD2oQEr8 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-JY0klfuDRD2oQEr8 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-JY0klfuDRD2oQEr8 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JY0klfuDRD2oQEr8 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-JY0klfuDRD2oQEr8 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JY0klfuDRD2oQEr8 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster text{fill:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 .cluster span{color:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-JY0klfuDRD2oQEr8 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-JY0klfuDRD2oQEr8 rect.text{fill:none;stroke-width:0;}#mermaid-svg-JY0klfuDRD2oQEr8 .icon-shape,#mermaid-svg-JY0klfuDRD2oQEr8 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-JY0klfuDRD2oQEr8 .icon-shape p,#mermaid-svg-JY0klfuDRD2oQEr8 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-JY0klfuDRD2oQEr8 .icon-shape .label rect,#mermaid-svg-JY0klfuDRD2oQEr8 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-JY0klfuDRD2oQEr8 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-JY0klfuDRD2oQEr8 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-JY0klfuDRD2oQEr8 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 大事务
锁持有时间长

→ 阻塞别的请求
undo log 膨胀

→ 占用大量空间
回滚代价高

→ 出事回滚很慢
主从延迟

→ 数据一致性风险

9.2 优化的思路

思路 做法
缩小事务范围 只把「必须原子」的操作放进事务,查询、日志、RPC 移出去
批量拆分 大批量更新,拆成小批量 + 分批提交
减少锁竞争 合理用索引,避免锁全表
异步化 非关键操作,事务提交后再异步处理

一句话 :事务越小越好------只包住「必须一起成功或一起失败」的那几行,其余的都挪出去。很多数据库性能问题,不是 SQL 慢,而是「事务太大了」。


十、事务与性能:几个实用建议

最后,发散地给几条「事务用得溜」的实用建议,都是经验之谈:

建议 说明
选对隔离级别 读多写少可用「读已提交」,别盲目用最严的
索引要给好 行锁需要索引定位,没索引会退化成锁表
避免长事务 事务里别干耗时的事(调外部接口、发邮件)
关注死锁日志 SHOW ENGINE INNODB STATUS 看死锁,对症下药
善用只读事务 纯查询可以标记为只读,减少开销

#mermaid-svg-ZvAS5YEK7822rysY{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-ZvAS5YEK7822rysY .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-ZvAS5YEK7822rysY .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-ZvAS5YEK7822rysY .error-icon{fill:#552222;}#mermaid-svg-ZvAS5YEK7822rysY .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-ZvAS5YEK7822rysY .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-ZvAS5YEK7822rysY .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-ZvAS5YEK7822rysY .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-ZvAS5YEK7822rysY .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-ZvAS5YEK7822rysY .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-ZvAS5YEK7822rysY .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-ZvAS5YEK7822rysY .marker{fill:#333333;stroke:#333333;}#mermaid-svg-ZvAS5YEK7822rysY .marker.cross{stroke:#333333;}#mermaid-svg-ZvAS5YEK7822rysY svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-ZvAS5YEK7822rysY p{margin:0;}#mermaid-svg-ZvAS5YEK7822rysY .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-ZvAS5YEK7822rysY .cluster-label text{fill:#333;}#mermaid-svg-ZvAS5YEK7822rysY .cluster-label span{color:#333;}#mermaid-svg-ZvAS5YEK7822rysY .cluster-label span p{background-color:transparent;}#mermaid-svg-ZvAS5YEK7822rysY .label text,#mermaid-svg-ZvAS5YEK7822rysY span{fill:#333;color:#333;}#mermaid-svg-ZvAS5YEK7822rysY .node rect,#mermaid-svg-ZvAS5YEK7822rysY .node circle,#mermaid-svg-ZvAS5YEK7822rysY .node ellipse,#mermaid-svg-ZvAS5YEK7822rysY .node polygon,#mermaid-svg-ZvAS5YEK7822rysY .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-ZvAS5YEK7822rysY .rough-node .label text,#mermaid-svg-ZvAS5YEK7822rysY .node .label text,#mermaid-svg-ZvAS5YEK7822rysY .image-shape .label,#mermaid-svg-ZvAS5YEK7822rysY .icon-shape .label{text-anchor:middle;}#mermaid-svg-ZvAS5YEK7822rysY .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-ZvAS5YEK7822rysY .rough-node .label,#mermaid-svg-ZvAS5YEK7822rysY .node .label,#mermaid-svg-ZvAS5YEK7822rysY .image-shape .label,#mermaid-svg-ZvAS5YEK7822rysY .icon-shape .label{text-align:center;}#mermaid-svg-ZvAS5YEK7822rysY .node.clickable{cursor:pointer;}#mermaid-svg-ZvAS5YEK7822rysY .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-ZvAS5YEK7822rysY .arrowheadPath{fill:#333333;}#mermaid-svg-ZvAS5YEK7822rysY .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-ZvAS5YEK7822rysY .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-ZvAS5YEK7822rysY .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZvAS5YEK7822rysY .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-ZvAS5YEK7822rysY .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZvAS5YEK7822rysY .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-ZvAS5YEK7822rysY .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-ZvAS5YEK7822rysY .cluster text{fill:#333;}#mermaid-svg-ZvAS5YEK7822rysY .cluster span{color:#333;}#mermaid-svg-ZvAS5YEK7822rysY div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-ZvAS5YEK7822rysY .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-ZvAS5YEK7822rysY rect.text{fill:none;stroke-width:0;}#mermaid-svg-ZvAS5YEK7822rysY .icon-shape,#mermaid-svg-ZvAS5YEK7822rysY .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-ZvAS5YEK7822rysY .icon-shape p,#mermaid-svg-ZvAS5YEK7822rysY .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-ZvAS5YEK7822rysY .icon-shape .label rect,#mermaid-svg-ZvAS5YEK7822rysY .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-ZvAS5YEK7822rysY .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-ZvAS5YEK7822rysY .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-ZvAS5YEK7822rysY :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 高并发
合理隔离级别
缩小事务
好索引
少锁竞争
又稳又快


写在最后

我们从一笔「转丢的钱」出发,把 MySQL 事务这个「玄学」概念,发散地、完整地过了一遍。回顾这条主线:

  1. 事务 = 一组操作「要么全成,要么全败」,靠 InnoDB 提供;
  2. ACID 四大特性:原子性靠 undo log、持久性靠 redo log、隔离性靠锁 + MVCC;
  3. 三大并发问题:脏读、不可重复读、幻读,一个比一个隐蔽;
  4. 四大隔离级别:MySQL 默认「可重复读」,越严越安全也越慢;
  5. MVCC 用「多版本 + 快照」实现读不阻塞写;
  6. 管写,行锁粒度细,但用不好会死锁;
  7. 传播行为 决定嵌套事务「听谁的」;
  8. 事务失效 大多因为代理没生效、或异常没让事务知道;
  9. 大事务 是性能杀手,越小越好;
  10. 用好事务,靠「选对级别、给好索引、缩小范围」。
相关推荐
lzhdim1 小时前
提高 SQL 语句执行速度的方法
java·开发语言·数据库·sql·oracle
ltl2 小时前
ClickHouse Distributed 引擎与分布式查询路由
数据库
Wang's Blog2 小时前
PostgreSQL笔记60: 权限与角色管理——从层级体系到最佳实践
数据库·笔记·postgresql
whcyhhh2 小时前
头歌实践教学平台:大数据存储2023(六)
大数据·数据库·python
Elastic 中国社区官方博客4 小时前
让大模型思考,让小模型执行:在 Elastic Workflows 中拆分 LLM 成本
大数据·运维·数据库·人工智能·elasticsearch·ai
Faith_xzc4 小时前
一条 SQL 顶一条 Flink 链路?Doris Streaming Job 持续导入全景解析
大数据·数据库·sql·flink
阮胜昌5 小时前
MySQL 中的动态数据脱敏:无需更改应用程序即可保护敏感数据
android·mysql·adb
小白说大模型6 小时前
AI驱动的个性化学习路径:知识图谱与知识点关联的存储与推理
大数据·人工智能·学习·mysql·机器学习·prompt·知识图谱
这个DBA有点耶7 小时前
多模数据库深度解读:从“多库拼装”到“一库多能”的架构演进
数据库·mysql·dba