You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3209 lines
81 KiB
HTML

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!doctype html>
<html lang="zh" class="no-js">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<meta name="description" content="开发知识wiki">
<meta name="author" content="tink">
<link rel="canonical" href="https://docs.cyub.vip/dev-wiki/database/mysql/%E4%BA%8B%E5%8A%A1/">
<link rel="prev" href="../%E7%AE%80%E4%BB%8B/">
<link rel="next" href="../%E7%B4%A2%E5%BC%95/">
<link rel="icon" href="../../../images/favicon.ico">
<meta name="generator" content="mkdocs-1.5.3, mkdocs-material-9.4.4">
<title>事务 - 开发知识wiki</title>
<link rel="stylesheet" href="../../../assets/stylesheets/main.bd3936ea.min.css">
<link rel="stylesheet" href="../../../assets/stylesheets/palette.356b1318.min.css">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Fira+Code:300,300i,400,400i,700,700i%7CFira+Code:400,400i,700,700i&display=fallback">
<style>:root{--md-text-font:"Fira Code";--md-code-font:"Fira Code"}</style>
<link rel="stylesheet" href="../../../css/print-site-enum-headings1.css">
<link rel="stylesheet" href="../../../css/print-site-enum-headings2.css">
<link rel="stylesheet" href="../../../css/print-site-enum-headings3.css">
<link rel="stylesheet" href="../../../css/print-site-enum-headings4.css">
<link rel="stylesheet" href="../../../css/print-site-enum-headings5.css">
<link rel="stylesheet" href="../../../css/print-site-enum-headings6.css">
<link rel="stylesheet" href="../../../css/print-site.css">
<link rel="stylesheet" href="../../../css/print-site-material.css">
<script>__md_scope=new URL("../../..",location),__md_hash=e=>[...e].reduce((e,_)=>(e<<5)-e+_.charCodeAt(0),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script>
<script id="__analytics">function __md_analytics(){function n(){dataLayer.push(arguments)}window.dataLayer=window.dataLayer||[],n("js",new Date),n("config",""),document.addEventListener("DOMContentLoaded",function(){document.forms.search&&document.forms.search.query.addEventListener("blur",function(){this.value&&n("event","search",{search_term:this.value})}),document$.subscribe(function(){var a=document.forms.feedback;if(void 0!==a)for(var e of a.querySelectorAll("[type=submit]"))e.addEventListener("click",function(e){e.preventDefault();var t=document.location.pathname,e=this.getAttribute("data-md-value");n("event","feedback",{page:t,data:e}),a.firstElementChild.disabled=!0;e=a.querySelector(".md-feedback__note [data-md-value='"+e+"']");e&&(e.hidden=!1)}),a.hidden=!1}),location$.subscribe(function(e){n("config","",{page_path:e.pathname})})});var e=document.createElement("script");e.async=!0,e.src="https://www.googletagmanager.com/gtag/js?id=",document.getElementById("__analytics").insertAdjacentElement("afterEnd",e)}</script>
<script>"undefined"!=typeof __md_analytics&&__md_analytics()</script>
<link href="../../../assets/stylesheets/glightbox.min.css" rel="stylesheet"/><style>
html.glightbox-open { overflow: initial; height: 100%; }
.gslide-title { margin-top: 0px; user-select: text; }
.gslide-desc { color: #666; user-select: text; }
.gslide-image img { background: white; }
.gscrollbar-fixer { padding-right: 15px; }
.gdesc-inner { font-size: 0.75rem; }
body[data-md-color-scheme="slate"] .gdesc-inner { background: var(--md-default-bg-color);}
body[data-md-color-scheme="slate"] .gslide-title { color: var(--md-default-fg-color);}
body[data-md-color-scheme="slate"] .gslide-desc { color: var(--md-default-fg-color);}</style> <script src="../../../assets/javascripts/glightbox.min.js"></script></head>
<body dir="ltr" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo">
<script>var palette=__md_get("__palette");if(palette&&"object"==typeof palette.color)for(var key of Object.keys(palette.color))document.body.setAttribute("data-md-color-"+key,palette.color[key])</script>
<input class="md-toggle" data-md-toggle="drawer" type="checkbox" id="__drawer" autocomplete="off">
<input class="md-toggle" data-md-toggle="search" type="checkbox" id="__search" autocomplete="off">
<label class="md-overlay" for="__drawer"></label>
<div data-md-component="skip">
<a href="#_1" class="md-skip">
跳转至
</a>
</div>
<div data-md-component="announce">
</div>
<header class="md-header" data-md-component="header">
<nav class="md-header__inner md-grid" aria-label="页眉">
<a href="../../.." title="开发知识wiki" class="md-header__button md-logo" aria-label="开发知识wiki" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 89 89">
<path d="M3.136,17.387l0,42.932l42.932,21.467l-42.932,-64.399Z" />
<path d="M21.91,8l42.933,64.398l-18.775,9.388l-42.932,-64.399l18.774,-9.387Z" style="fill-opacity: 0.5" />
<path d="M67.535,17.387l-27.262,18.156l21.878,32.818l5.384,2.691l0,-53.665Z" />
<path d="M67.535,17.387l0,53.666l18.774,-9.388l0,-53.665l-18.774,9.387Z" style="fill-opacity: 0.25" />
</svg>
</a>
<label class="md-header__button md-icon" for="__drawer">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3 6h18v2H3V6m0 5h18v2H3v-2m0 5h18v2H3v-2Z"/></svg>
</label>
<div class="md-header__title" data-md-component="header-title">
<div class="md-header__ellipsis">
<div class="md-header__topic">
<span class="md-ellipsis">
开发知识wiki
</span>
</div>
<div class="md-header__topic" data-md-component="header-topic">
<span class="md-ellipsis">
事务
</span>
</div>
</div>
</div>
<form class="md-header__option" data-md-component="palette">
<input class="md-option" data-md-color-media="(prefers-color-scheme)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to light mode" type="radio" name="__palette" id="__palette_1">
<label class="md-header__button md-icon" title="Switch to light mode" for="__palette_3" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M3.9 12c0-1.71 1.39-3.1 3.1-3.1h4V7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h4v-1.9H7c-1.71 0-3.1-1.39-3.1-3.1M8 13h8v-2H8v2m9-6h-4v1.9h4c1.71 0 3.1 1.39 3.1 3.1 0 1.71-1.39 3.1-3.1 3.1h-4V17h4a5 5 0 0 0 5-5 5 5 0 0 0-5-5Z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme="default" data-md-color-primary="indigo" data-md-color-accent="indigo" aria-label="Switch to dark mode" type="radio" name="__palette" id="__palette_2">
<label class="md-header__button md-icon" title="Switch to dark mode" for="__palette_1" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5m0 8a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3Z"/></svg>
</label>
<input class="md-option" data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme="slate" data-md-color-primary="black" data-md-color-accent="indigo" aria-label="Switch to system preference" type="radio" name="__palette" id="__palette_3">
<label class="md-header__button md-icon" title="Switch to system preference" for="__palette_2" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M17 7H7a5 5 0 0 0-5 5 5 5 0 0 0 5 5h10a5 5 0 0 0 5-5 5 5 0 0 0-5-5M7 15a3 3 0 0 1-3-3 3 3 0 0 1 3-3 3 3 0 0 1 3 3 3 3 0 0 1-3 3Z"/></svg>
</label>
</form>
<label class="md-header__button md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
</label>
<div class="md-search" data-md-component="search" role="dialog">
<label class="md-search__overlay" for="__search"></label>
<div class="md-search__inner" role="search">
<form class="md-search__form" name="search">
<input type="text" class="md-search__input" name="query" aria-label="搜索" placeholder="搜索" autocapitalize="off" autocorrect="off" autocomplete="off" spellcheck="false" data-md-component="search-query" required>
<label class="md-search__icon md-icon" for="__search">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.516 6.516 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</label>
<nav class="md-search__options" aria-label="查找">
<a href="javascript:void(0)" class="md-search__icon md-icon" title="分享" aria-label="分享" data-clipboard data-clipboard-text="" data-md-component="search-share" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7 0-.24-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9a3 3 0 0 0-3 3 3 3 0 0 0 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.15c-.05.21-.08.43-.08.66 0 1.61 1.31 2.91 2.92 2.91 1.61 0 2.92-1.3 2.92-2.91A2.92 2.92 0 0 0 18 16.08Z"/></svg>
</a>
<button type="reset" class="md-search__icon md-icon" title="清空当前内容" aria-label="清空当前内容" tabindex="-1">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M19 6.41 17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12 19 6.41Z"/></svg>
</button>
</nav>
<div class="md-search__suggest" data-md-component="search-suggest"></div>
</form>
<div class="md-search__output">
<div class="md-search__scrollwrap" data-md-scrollfix>
<div class="md-search-result" data-md-component="search-result">
<div class="md-search-result__meta">
正在初始化搜索引擎
</div>
<ol class="md-search-result__list" role="presentation"></ol>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
<div class="md-container" data-md-component="container">
<nav class="md-tabs" aria-label="标签" data-md-component="tabs">
<div class="md-grid">
<ul class="md-tabs__list">
<li class="md-tabs__item">
<a href="../../.." class="md-tabs__link">
简介
</a>
</li>
<li class="md-tabs__item">
<a href="../../../computer-system/io/" class="md-tabs__link">
操作系统
</a>
</li>
<li class="md-tabs__item">
<a href="../../../computer-network/tcp/" class="md-tabs__link">
计算机网络
</a>
</li>
<li class="md-tabs__item md-tabs__item--active">
<a href="../%E7%AE%80%E4%BB%8B/" class="md-tabs__link">
数据库
</a>
</li>
<li class="md-tabs__item">
<a href="../../../language/Go/" class="md-tabs__link">
开发语言
</a>
</li>
<li class="md-tabs__item">
<a href="../../../system-design/" class="md-tabs__link">
系统设计
</a>
</li>
<li class="md-tabs__item">
<a href="../../../jupyter/Go-Frameworks-Github-Fork-Stats/" class="md-tabs__link">
Jupyter
</a>
</li>
<li class="md-tabs__item">
<a href="../../../video/os/" class="md-tabs__link">
视频
</a>
</li>
<li class="md-tabs__item">
<a href="../../../qa/redis/" class="md-tabs__link">
QA
</a>
</li>
</ul>
</div>
</nav>
<main class="md-main" data-md-component="main">
<div class="md-main__inner md-grid">
<div class="md-sidebar md-sidebar--primary" data-md-component="sidebar" data-md-type="navigation" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--primary md-nav--lifted" aria-label="导航栏" data-md-level="0">
<label class="md-nav__title" for="__drawer">
<a href="../../.." title="开发知识wiki" class="md-nav__button md-logo" aria-label="开发知识wiki" data-md-component="logo">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 89 89">
<path d="M3.136,17.387l0,42.932l42.932,21.467l-42.932,-64.399Z" />
<path d="M21.91,8l42.933,64.398l-18.775,9.388l-42.932,-64.399l18.774,-9.387Z" style="fill-opacity: 0.5" />
<path d="M67.535,17.387l-27.262,18.156l21.878,32.818l5.384,2.691l0,-53.665Z" />
<path d="M67.535,17.387l0,53.666l18.774,-9.388l0,-53.665l-18.774,9.387Z" style="fill-opacity: 0.25" />
</svg>
</a>
开发知识wiki
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../.." class="md-nav__link">
<span class="md-ellipsis">
简介
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2" >
<label class="md-nav__link" for="__nav_2" id="__nav_2_label" tabindex="">
<span class="md-ellipsis">
操作系统
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2">
<span class="md-nav__icon md-icon"></span>
操作系统
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../computer-system/io/" class="md-nav__link">
<span class="md-ellipsis">
IO
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/proc/" class="md-nav__link">
<span class="md-ellipsis">
proc文件系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/nptl/" class="md-nav__link">
<span class="md-ellipsis">
NPTL
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_2_4" >
<label class="md-nav__link" for="__nav_2_4" id="__nav_2_4_label" tabindex="">
<span class="md-ellipsis">
容器
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_2_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_2_4">
<span class="md-nav__icon md-icon"></span>
容器
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../container/install/" class="md-nav__link">
<span class="md-ellipsis">
简介
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../container/image/" class="md-nav__link">
<span class="md-ellipsis">
镜像
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../container/cgroup/" class="md-nav__link">
<span class="md-ellipsis">
cgroup
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../container/namespace/" class="md-nav__link">
<span class="md-ellipsis">
namespace
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/command/" class="md-nav__link">
<span class="md-ellipsis">
常用命令
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/systemtap/" class="md-nav__link">
<span class="md-ellipsis">
Systemtap
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/cpu-arch/" class="md-nav__link">
<span class="md-ellipsis">
CPU架构
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../computer-system/compiling-linux-kernel/" class="md-nav__link">
<span class="md-ellipsis">
编译Linux内核
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_3" >
<div class="md-nav__link md-nav__container">
<a href="../../../computer-network/tcp/" class="md-nav__link ">
<span class="md-ellipsis">
计算机网络
</span>
</a>
<label class="md-nav__link " for="__nav_3" id="__nav_3_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_3">
<span class="md-nav__icon md-icon"></span>
计算机网络
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../computer-network/http/" class="md-nav__link">
<span class="md-ellipsis">
HTTP
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4" checked>
<label class="md-nav__link" for="__nav_4" id="__nav_4_label" tabindex="">
<span class="md-ellipsis">
数据库
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_4_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_4">
<span class="md-nav__icon md-icon"></span>
数据库
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item md-nav__item--active md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_1" checked>
<label class="md-nav__link" for="__nav_4_1" id="__nav_4_1_label" tabindex="">
<span class="md-ellipsis">
mysql
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_1_label" aria-expanded="true">
<label class="md-nav__title" for="__nav_4_1">
<span class="md-nav__icon md-icon"></span>
mysql
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../%E7%AE%80%E4%BB%8B/" class="md-nav__link">
<span class="md-ellipsis">
概览
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--active">
<input class="md-nav__toggle md-toggle" type="checkbox" id="__toc">
<label class="md-nav__link md-nav__link--active" for="__toc">
<span class="md-ellipsis">
事务
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<a href="./" class="md-nav__link md-nav__link--active">
<span class="md-ellipsis">
事务
</span>
</a>
<nav class="md-nav md-nav--secondary" aria-label="目录">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
目录
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#acid" class="md-nav__link">
ACID
</a>
</li>
<li class="md-nav__item">
<a href="#_2" class="md-nav__link">
隔离级别
</a>
<nav class="md-nav" aria-label="隔离级别">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_3" class="md-nav__link">
隔离级别配置
</a>
</li>
<li class="md-nav__item">
<a href="#_4" class="md-nav__link">
读取异常
</a>
<nav class="md-nav" aria-label="读取异常">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lost-update" class="md-nav__link">
Lost Update
</a>
</li>
<li class="md-nav__item">
<a href="#dirty-read-" class="md-nav__link">
Dirty Read - 脏读
</a>
</li>
<li class="md-nav__item">
<a href="#non-repeatable-read-" class="md-nav__link">
Non-Repeatable Read - 不可重复读
</a>
</li>
<li class="md-nav__item">
<a href="#phantom-read-" class="md-nav__link">
Phantom Read - 幻读
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_5" class="md-nav__link">
事务超时
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mvcc" class="md-nav__link">
MVCC
</a>
<nav class="md-nav" aria-label="MVCC">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mysqlinnodbmvcc" class="md-nav__link">
MySQL的InnoDB存储引擎实现MVCC的策略
</a>
</li>
<li class="md-nav__item">
<a href="#_6" class="md-nav__link">
快照读和当前读
</a>
<nav class="md-nav" aria-label="快照读和当前读">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_7" class="md-nav__link">
快照读
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_8" class="md-nav__link">
当前读
</a>
</li>
<li class="md-nav__item">
<a href="#_9" class="md-nav__link">
总结
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_10" class="md-nav__link">
事务日志
</a>
</li>
<li class="md-nav__item">
<a href="#_11" class="md-nav__link">
参考资料
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../%E7%B4%A2%E5%BC%95/" class="md-nav__link">
<span class="md-ellipsis">
索引
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../FAQ/" class="md-nav__link">
<span class="md-ellipsis">
FAQ
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_4_2" >
<div class="md-nav__link md-nav__container">
<a href="../../elasticsearch/" class="md-nav__link ">
<span class="md-ellipsis">
Elasticsearch
</span>
</a>
<label class="md-nav__link " for="__nav_4_2" id="__nav_4_2_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_4_2_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_4_2">
<span class="md-nav__icon md-icon"></span>
Elasticsearch
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../elasticsearch/memory/" class="md-nav__link">
<span class="md-ellipsis">
内存占用
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../elasticsearch/performance_tuning/" class="md-nav__link">
<span class="md-ellipsis">
性能调优
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../elasticsearch/production_configuring/" class="md-nav__link">
<span class="md-ellipsis">
生产配置参考
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../elasticsearch/doc_values_and_fielddata/" class="md-nav__link">
<span class="md-ellipsis">
docs value与 field data
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="../../redis/redis/" class="md-nav__link">
<span class="md-ellipsis">
Redis
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_5" >
<label class="md-nav__link" for="__nav_5" id="__nav_5_label" tabindex="">
<span class="md-ellipsis">
开发语言
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_5">
<span class="md-nav__icon md-icon"></span>
开发语言
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../language/Go/" class="md-nav__link">
<span class="md-ellipsis">
Go
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6" >
<div class="md-nav__link md-nav__container">
<a href="../../../system-design/" class="md-nav__link ">
<span class="md-ellipsis">
系统设计
</span>
</a>
<label class="md-nav__link " for="__nav_6" id="__nav_6_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_6_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6">
<span class="md-nav__icon md-icon"></span>
系统设计
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../cache/" class="md-nav__link">
<span class="md-ellipsis">
缓存系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../system-design/system-design-primer/" class="md-nav__link">
<span class="md-ellipsis">
系统设计入门
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_4" >
<div class="md-nav__link md-nav__container">
<a href="../../../what-should-you-know/" class="md-nav__link ">
<span class="md-ellipsis">
what you should know
</span>
</a>
<label class="md-nav__link " for="__nav_6_4" id="__nav_6_4_label" tabindex="">
<span class="md-nav__icon md-icon"></span>
</label>
</div>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_6_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_4">
<span class="md-nav__icon md-icon"></span>
what you should know
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../what-should-you-know/GPU/" class="md-nav__link">
<span class="md-ellipsis">
每个开发人员都应该了解 GPU 计算的知识
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../what-should-you-know/hardware/" class="md-nav__link">
<span class="md-ellipsis">
每个程序员都应该了解的硬件知识
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_4_4" >
<label class="md-nav__link" for="__nav_6_4_4" id="__nav_6_4_4_label" tabindex="0">
<span class="md-ellipsis">
每个程序员都应该了解的内存知识
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_6_4_4_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_4_4">
<span class="md-nav__icon md-icon"></span>
每个程序员都应该了解的内存知识
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../what-should-you-know/%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E5%BA%94%E8%AF%A5%E4%BA%86%E8%A7%A3%E7%9A%84%E5%86%85%E5%AD%98%E7%9F%A5%E8%AF%86/" class="md-nav__link">
<span class="md-ellipsis">
【总结版】每个程序员都应该了解的内存知识
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../what-should-you-know/What%20Every%20Programmer%20Should%20Know%20About%20Memory.pdf" class="md-nav__link">
<span class="md-ellipsis">
【英文】What Every Programmer Should Know About Memory
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../what-should-you-know/%E6%AF%8F%E4%B8%AA%E7%A8%8B%E5%BA%8F%E5%91%98%E9%83%BD%E5%BA%94%E8%AF%A5%E4%BA%86%E8%A7%A3%E7%9A%84%E5%86%85%E5%AD%98%E7%9F%A5%E8%AF%86.pdf" class="md-nav__link">
<span class="md-ellipsis">
【中文】每个程序员都应该了解的内存知识
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_6_4_5" >
<label class="md-nav__link" for="__nav_6_4_5" id="__nav_6_4_5_label" tabindex="0">
<span class="md-ellipsis">
每个系统程序员都应该了解的并发知识
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="3" aria-labelledby="__nav_6_4_5_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_6_4_5">
<span class="md-nav__icon md-icon"></span>
每个系统程序员都应该了解的并发知识
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../what-should-you-know/concurrency-primer.pdf" class="md-nav__link">
<span class="md-ellipsis">
【英文】What every systems programmer should know about concurrency
</span>
</a>
</li>
<li class="md-nav__item">
<a href="https://www.bilibili.com/read/cv26734224" class="md-nav__link">
<span class="md-ellipsis">
【中文】每个系统程序员都应该了解的并发知识
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7" >
<label class="md-nav__link" for="__nav_7" id="__nav_7_label" tabindex="">
<span class="md-ellipsis">
Jupyter
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_7_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7">
<span class="md-nav__icon md-icon"></span>
Jupyter
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../jupyter/Go-Frameworks-Github-Fork-Stats/" class="md-nav__link">
<span class="md-ellipsis">
Go-Frameworks-Github-Fork-Stats
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../jupyter/Pandas%E5%AE%8C%E5%85%A8%E6%8C%87%E5%8D%97/" class="md-nav__link">
<span class="md-ellipsis">
Pandas完全指南
</span>
</a>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_7_3" >
<label class="md-nav__link" for="__nav_7_3" id="__nav_7_3_label" tabindex="">
<span class="md-ellipsis">
Spark上手示例
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="2" aria-labelledby="__nav_7_3_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_7_3">
<span class="md-nav__icon md-icon"></span>
Spark上手示例
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../jupyter/Spark%E4%B8%8A%E6%89%8B%E7%A4%BA%E4%BE%8B1%EF%BC%9ARDD%E6%93%8D%E4%BD%9C/" class="md-nav__link">
<span class="md-ellipsis">
Spark上手示例1RDD操作
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../jupyter/Spark%E4%B8%8A%E6%89%8B%E7%A4%BA%E4%BE%8B2%EF%BC%9ADataFrame%E6%93%8D%E4%BD%9C/" class="md-nav__link">
<span class="md-ellipsis">
Spark上手示例2DataFrame操作
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_8" >
<label class="md-nav__link" for="__nav_8" id="__nav_8_label" tabindex="">
<span class="md-ellipsis">
视频
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_8_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_8">
<span class="md-nav__icon md-icon"></span>
视频
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../video/os/" class="md-nav__link">
<span class="md-ellipsis">
操作系统
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../video/Data%20structures/" class="md-nav__link">
<span class="md-ellipsis">
数据结构与算法
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../video/c_c%2B%2B/" class="md-nav__link">
<span class="md-ellipsis">
C/C++
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../video/Go/" class="md-nav__link">
<span class="md-ellipsis">
Go
</span>
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item md-nav__item--section md-nav__item--nested">
<input class="md-nav__toggle md-toggle " type="checkbox" id="__nav_9" >
<label class="md-nav__link" for="__nav_9" id="__nav_9_label" tabindex="">
<span class="md-ellipsis">
QA
</span>
<span class="md-nav__icon md-icon"></span>
</label>
<nav class="md-nav" data-md-level="1" aria-labelledby="__nav_9_label" aria-expanded="false">
<label class="md-nav__title" for="__nav_9">
<span class="md-nav__icon md-icon"></span>
QA
</label>
<ul class="md-nav__list" data-md-scrollfix>
<li class="md-nav__item">
<a href="../../../qa/redis/" class="md-nav__link">
<span class="md-ellipsis">
redis
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/mysql/" class="md-nav__link">
<span class="md-ellipsis">
mysql
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/tcp/" class="md-nav__link">
<span class="md-ellipsis">
tcp
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/http/" class="md-nav__link">
<span class="md-ellipsis">
http
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/cache/" class="md-nav__link">
<span class="md-ellipsis">
缓存
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/nginx/" class="md-nav__link">
<span class="md-ellipsis">
nginx
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/queue/" class="md-nav__link">
<span class="md-ellipsis">
消息队列
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/io/" class="md-nav__link">
<span class="md-ellipsis">
IO
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/protobuf/" class="md-nav__link">
<span class="md-ellipsis">
protobuf
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/go/" class="md-nav__link">
<span class="md-ellipsis">
go
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/dist/" class="md-nav__link">
<span class="md-ellipsis">
分布式
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/es/" class="md-nav__link">
<span class="md-ellipsis">
Elasticsearch
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/docker/" class="md-nav__link">
<span class="md-ellipsis">
docker
</span>
</a>
</li>
<li class="md-nav__item">
<a href="../../../qa/ref/" class="md-nav__link">
<span class="md-ellipsis">
参考资料
</span>
</a>
</li>
</ul>
</nav>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-sidebar md-sidebar--secondary" data-md-component="sidebar" data-md-type="toc" >
<div class="md-sidebar__scrollwrap">
<div class="md-sidebar__inner">
<nav class="md-nav md-nav--secondary" aria-label="目录">
<label class="md-nav__title" for="__toc">
<span class="md-nav__icon md-icon"></span>
目录
</label>
<ul class="md-nav__list" data-md-component="toc" data-md-scrollfix>
<li class="md-nav__item">
<a href="#acid" class="md-nav__link">
ACID
</a>
</li>
<li class="md-nav__item">
<a href="#_2" class="md-nav__link">
隔离级别
</a>
<nav class="md-nav" aria-label="隔离级别">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_3" class="md-nav__link">
隔离级别配置
</a>
</li>
<li class="md-nav__item">
<a href="#_4" class="md-nav__link">
读取异常
</a>
<nav class="md-nav" aria-label="读取异常">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#lost-update" class="md-nav__link">
Lost Update
</a>
</li>
<li class="md-nav__item">
<a href="#dirty-read-" class="md-nav__link">
Dirty Read - 脏读
</a>
</li>
<li class="md-nav__item">
<a href="#non-repeatable-read-" class="md-nav__link">
Non-Repeatable Read - 不可重复读
</a>
</li>
<li class="md-nav__item">
<a href="#phantom-read-" class="md-nav__link">
Phantom Read - 幻读
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_5" class="md-nav__link">
事务超时
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#mvcc" class="md-nav__link">
MVCC
</a>
<nav class="md-nav" aria-label="MVCC">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#mysqlinnodbmvcc" class="md-nav__link">
MySQL的InnoDB存储引擎实现MVCC的策略
</a>
</li>
<li class="md-nav__item">
<a href="#_6" class="md-nav__link">
快照读和当前读
</a>
<nav class="md-nav" aria-label="快照读和当前读">
<ul class="md-nav__list">
<li class="md-nav__item">
<a href="#_7" class="md-nav__link">
快照读
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_8" class="md-nav__link">
当前读
</a>
</li>
<li class="md-nav__item">
<a href="#_9" class="md-nav__link">
总结
</a>
</li>
</ul>
</nav>
</li>
<li class="md-nav__item">
<a href="#_10" class="md-nav__link">
事务日志
</a>
</li>
<li class="md-nav__item">
<a href="#_11" class="md-nav__link">
参考资料
</a>
</li>
</ul>
</nav>
</div>
</div>
</div>
<div class="md-content" data-md-component="content">
<article class="md-content__inner md-typeset">
<h1 id="_1">事务<a class="headerlink" href="#_1" title="Permanent link">&para;</a></h1>
<h2 id="acid">ACID<a class="headerlink" href="#acid" title="Permanent link">&para;</a></h2>
<ul>
<li>
<p><strong>原子性:</strong> 事务是最小的执行单位,不允许分割。事务的原子性确保动作要么全部完成,要么完全不起作用;</p>
</li>
<li>
<p><strong>一致性:</strong> 执行事务前后,数据保持一致;</p>
</li>
<li>
<p><strong>隔离性:</strong> 并发访问数据库时,一个用户的事物不被其他事物所干扰,各并发事务之间数据库是独立的;</p>
</li>
<li>
<p><strong>持久性:</strong> 一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库 发生故障也不应该对其有任何影响。</p>
</li>
</ul>
<h2 id="_2">隔离级别<a class="headerlink" href="#_2" title="Permanent link">&para;</a></h2>
<p>事务隔离级别 (transaction isolation levels),隔离级别就是对对事务并发控制的等级。</p>
<p>很多 DBMS 定义了不同的 “事务隔离等级” 来控制锁的程度,多数的数据库事务都避免高等级的隔离等级 (如可序列化) 从而减少对系统的锁的开销,高的隔离级别往往会增加死锁发生的几率。</p>
<h3 id="_3">隔离级别配置<a class="headerlink" href="#_3" title="Permanent link">&para;</a></h3>
<p>InnoDB 默认是可重复读的 (REPEATABLE READ),提供 SQL-92 标准所描述的所有四个事务隔离级别,可以在启动时用 --transaction-isolation 选项设置,也可以配置文件中设置。</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-0-1"><a id="__codelineno-0-1" name="__codelineno-0-1" href="#__codelineno-0-1"></a>$ cat /etc/my.cnf
</span><span id="__span-0-2"><a id="__codelineno-0-2" name="__codelineno-0-2" href="#__codelineno-0-2"></a>[mysqld]
</span><span id="__span-0-3"><a id="__codelineno-0-3" name="__codelineno-0-3" href="#__codelineno-0-3"></a>transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED | REPEATABLE-READ | SERIALIZABLE}
</span></code></pre></div>
<p>用户可以用 SET TRANSACTION 语句改变单个会话或者所有新进连接的隔离级别,语法如下:</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-1-1"><a id="__codelineno-1-1" name="__codelineno-1-1" href="#__codelineno-1-1"></a>mysql&gt; SET autocommit=0;
</span><span id="__span-1-2"><a id="__codelineno-1-2" name="__codelineno-1-2" href="#__codelineno-1-2"></a>mysql&gt; SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
</span><span id="__span-1-3"><a id="__codelineno-1-3" name="__codelineno-1-3" href="#__codelineno-1-3"></a> {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE}
</span></code></pre></div>
<p>如果使用 GLOBAL 关键字,当然需要 SUPER 权限,则从设置时间点开始创建的所有新连接均采用该默认事务级别,不过原有链接事务隔离级别不变。</p>
<p>可以用下列语句查询全局和会话事务隔离级别。</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-2-1"><a id="__codelineno-2-1" name="__codelineno-2-1" href="#__codelineno-2-1"></a>mysql&gt; SHOW VARIABLES LIKE &#39;tx_isolation&#39;;
</span><span id="__span-2-2"><a id="__codelineno-2-2" name="__codelineno-2-2" href="#__codelineno-2-2"></a>mysql&gt; SELECT @@global.tx_isolation;
</span><span id="__span-2-3"><a id="__codelineno-2-3" name="__codelineno-2-3" href="#__codelineno-2-3"></a>mysql&gt; SELECT @@session.tx_isolation;
</span><span id="__span-2-4"><a id="__codelineno-2-4" name="__codelineno-2-4" href="#__codelineno-2-4"></a>mysql&gt; SELECT @@tx_isolation;
</span></code></pre></div>
<h3 id="_4">读取异常<a class="headerlink" href="#_4" title="Permanent link">&para;</a></h3>
<p>在 SQL 92 规范的定义中,规定了四种隔离级别,同时对可能出现的三种现象进行了说明(不包含如下的丢失更新)。</p>
<h4 id="lost-update">Lost Update<a class="headerlink" href="#lost-update" title="Permanent link">&para;</a></h4>
<p>丢失更新,当两个事务读取相同数据,然后都尝试更新原来的数据成新的值,此时,第二个事务可能完全覆盖掉第一个所完成的更新。</p>
<p>丢失更新是唯一一个用户可能在所有情况下都想避免的行为,在 SQL 92 中甚至没有提及。</p>
<h4 id="dirty-read-">Dirty Read - 脏读<a class="headerlink" href="#dirty-read-" title="Permanent link">&para;</a></h4>
<p>一个事务中读取到另一个事务未提交的数据。例如,事务 T1 读取到另一个事务 T2 未提交的数据,如果 T2 回滚,则 T1 相当于读取到了一个被认为不可能出现的值。</p>
<h4 id="non-repeatable-read-">Non-Repeatable Read - 不可重复读<a class="headerlink" href="#non-repeatable-read-" title="Permanent link">&para;</a></h4>
<p><strong>在一个事务中,当重复读取同一条记录时,发现该记录的结果不同或者已经被删除了</strong>;如在事务 T1 中读取了一行,接着 T2 修改或者删除了该行并提交,那么当 T1 尝试读取新的值时,就会发现改行的值已经修改或者被删除。</p>
<h4 id="phantom-read-">Phantom Read - 幻读<a class="headerlink" href="#phantom-read-" title="Permanent link">&para;</a></h4>
<p>通常是指在一个事务中,当重复查询一个结果集时,返回的两个不同的结果集,可能是由于另一个事务插入或者删除了一些记录。</p>
<p>例如,事务 T1 读取一个结果集T2 修改了该结果集中的部分记录 (例如插入一条记录)T1 再次读取时发现与之前的结果不同 (多出来一条记录),就像产生幻觉一样。</p>
<p><strong>不可重复读与幻读的区别:</strong></p>
<p><strong>不可重复读的重点是修改:同样的条件, 你读取过的数据, 再次读取出来发现值不一样了</strong>,其只需要锁住满足条件的记录</p>
<p><strong>幻读的重点在于新增或者删除:同样的条件, 第1次和第2次读出来的记录数不一样</strong>,要锁住满足条件及其相近的记录</p>
<p>如果使用锁机制来实现这两种隔离级别在可重复读中该sql第一次读取到数据后就将这些数据加锁其它事务无法修改这些数据就可以实现可重复读了。但这种方法却无法锁住insert的数据所以当事务A先前读取了数据或者修改了全部数据事务B还是可以insert数据提交这时事务A就会 发现莫名其妙多了一条之前没有的数据这就是幻读不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力,因为解决幻读需要锁表了。</p>
<p>mysql是以乐观锁为理论基础的MVCC多版本并发控制来避免不可重复度和幻读的。</p>
<table>
<thead>
<tr>
<th>隔离级别</th>
<th>脏读</th>
<th>不可重复读取</th>
<th>幻影数据行</th>
</tr>
</thead>
<tbody>
<tr>
<td>READ UNCOMMITTED(RU) - 读未提交</td>
<td>YES</td>
<td>YES</td>
<td>YES</td>
</tr>
<tr>
<td>READ COMMITTED(RC) - 读已提交</td>
<td>NO</td>
<td>YES</td>
<td>YES</td>
</tr>
<tr>
<td>REPEATABLE READ(RR) - 可重复读</td>
<td>NO</td>
<td>NO</td>
<td>YES</td>
</tr>
<tr>
<td>SERIALIZABLE(SZ) - 串行化</td>
<td>NO</td>
<td>NO</td>
<td>NO</td>
</tr>
</tbody>
</table>
<h3 id="_5">事务超时<a class="headerlink" href="#_5" title="Permanent link">&para;</a></h3>
<p>与事务超时相关的变量可以参考。</p>
<div class="language-text highlight"><pre><span></span><code><span id="__span-3-1"><a id="__codelineno-3-1" name="__codelineno-3-1" href="#__codelineno-3-1"></a>----- 设置锁超时时间单位为秒默认50s
</span><span id="__span-3-2"><a id="__codelineno-3-2" name="__codelineno-3-2" href="#__codelineno-3-2"></a>mysql&gt; SHOW VARIABLES LIKE &#39;innodb_lock_wait_timeout&#39;;
</span><span id="__span-3-3"><a id="__codelineno-3-3" name="__codelineno-3-3" href="#__codelineno-3-3"></a>+--------------------------+-------+
</span><span id="__span-3-4"><a id="__codelineno-3-4" name="__codelineno-3-4" href="#__codelineno-3-4"></a>| Variable_name | Value |
</span><span id="__span-3-5"><a id="__codelineno-3-5" name="__codelineno-3-5" href="#__codelineno-3-5"></a>+--------------------------+-------+
</span><span id="__span-3-6"><a id="__codelineno-3-6" name="__codelineno-3-6" href="#__codelineno-3-6"></a>| innodb_lock_wait_timeout | 50 |
</span><span id="__span-3-7"><a id="__codelineno-3-7" name="__codelineno-3-7" href="#__codelineno-3-7"></a>+--------------------------+-------+
</span><span id="__span-3-8"><a id="__codelineno-3-8" name="__codelineno-3-8" href="#__codelineno-3-8"></a>1 row in set (0.00 sec)
</span><span id="__span-3-9"><a id="__codelineno-3-9" name="__codelineno-3-9" href="#__codelineno-3-9"></a>
</span><span id="__span-3-10"><a id="__codelineno-3-10" name="__codelineno-3-10" href="#__codelineno-3-10"></a>----- 超时后的行为默认OFF详见如下介绍
</span><span id="__span-3-11"><a id="__codelineno-3-11" name="__codelineno-3-11" href="#__codelineno-3-11"></a>mysql&gt; SHOW VARIABLES LIKE &#39;innodb_rollback_on_timeout&#39;;
</span><span id="__span-3-12"><a id="__codelineno-3-12" name="__codelineno-3-12" href="#__codelineno-3-12"></a>+----------------------------+-------+
</span><span id="__span-3-13"><a id="__codelineno-3-13" name="__codelineno-3-13" href="#__codelineno-3-13"></a>| Variable_name | Value |
</span><span id="__span-3-14"><a id="__codelineno-3-14" name="__codelineno-3-14" href="#__codelineno-3-14"></a>+----------------------------+-------+
</span><span id="__span-3-15"><a id="__codelineno-3-15" name="__codelineno-3-15" href="#__codelineno-3-15"></a>| innodb_rollback_on_timeout | OFF |
</span><span id="__span-3-16"><a id="__codelineno-3-16" name="__codelineno-3-16" href="#__codelineno-3-16"></a>+----------------------------+-------+
</span><span id="__span-3-17"><a id="__codelineno-3-17" name="__codelineno-3-17" href="#__codelineno-3-17"></a>1 row in set (0.02 sec)
</span></code></pre></div>
<p>innodb_rollback_on_timeout 变量默认值为 OFF如果事务因为加锁超时会回滚上一条语句执行的操作如果设置 ON则整个事务都会回滚。</p>
<h2 id="mvcc">MVCC<a class="headerlink" href="#mvcc" title="Permanent link">&para;</a></h2>
<p>MVCCMulti-Version Concurrency Control即多版本并发控制MVCC 是一种并发控制的方法,以乐观锁的方式解决事务中不可重复读和幻读的问题。</p>
<p>MVCC是行级锁的一个变种但是它在很多情况下避免了加锁操作因此开销更低。MVCC实现了非阻塞的读操作写操作也只是锁定必要的行。MVCC会保存某个时间点上的数据快照(Snapshot)。这意味着事务可以看到一个一致的数据视图,不管他们需要跑多久。这同时也意味着不同的事务在同一个时间点看到的同一个表的数据可能是不同的。</p>
<h3 id="mysqlinnodbmvcc">MySQL的InnoDB存储引擎实现MVCC的策略<a class="headerlink" href="#mysqlinnodbmvcc" title="Permanent link">&para;</a></h3>
<p>InnoDB默认事务隔离级别是可重复读。InnoDB的MVCC是通过在每行记录后面保存两个隐藏的列来实现。这两个列一个保存了行的创建时间一个保存了行的过期时间或删除时间)。当然存储的并不是实际的时间值,而是系统版本号(system version number)。每开始一个新的事务,系统版本号都会自动递增。事务开始时刻的系统版本号会作为事务的版本号,用来查询到的每行记录的版本号进行比较。</p>
<p><strong>Select操作</strong></p>
<p>InnoDB会根据以下两个条件检查每行记录。</p>
<ol>
<li>
<p>InnoDB只查找版本号早于当前事务版本的数据行即行的版本号小于或等于事务的系统的版本号这可以确保事务读取的行要么是在事务开始前已经存在的要么是事务自身插入或者修改过过的。</p>
</li>
<li>
<p>行的删除版本要么未定义,要么大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除。</p>
</li>
</ol>
<p><strong>INSERT操作</strong></p>
<p>InnoDB为新插入的每一行保存当前系统版本号作为行版本号</p>
<p><strong>DELETE操作</strong></p>
<p>InnoDB为删除的每一行保存当前系统版本号作为行删除标识</p>
<p><strong>UPDATE操作</strong></p>
<p>InnoDB为插入一行新记录保存当前系统版本号作为行版本号同时保存当前系统版本号到原来的行作为删除标识这只是理论innoDB实际是通过undo log来备份旧记录的</p>
<p>MVCC 只在 REPEATABLE READ 和 READ COMMITTED 两个隔离级别下工作。其他两个隔离级别都和MVCC不兼容因为 READ UNCOMMITTED 总是读取最新的数据行而不是符合当前事务版本的数据行。SERIALIZABLE则会对所有读取的行都加锁。</p>
<h3 id="_6">快照读和当前读<a class="headerlink" href="#_6" title="Permanent link">&para;</a></h3>
<h4 id="_7">快照读<a class="headerlink" href="#_7" title="Permanent link">&para;</a></h4>
<p>快照读 即snapshot read官方叫法是Consistent Nonlocking Reads一致性非锁定读。只能看到 别的事务生成快照前提交的数据,而不能看到 别的事务生成快照后提交的数据或者未提交的数据。</p>
<p>快照读 是 repeatable-read 和 read-committed 级别下,默认的查询模式,好处是:读不加锁,读写不冲突,这个对于 MySQL 并发访问提升很大。</p>
<p>快照读读取的是快照版本也就是历史版本。普通的SELECT就是快照读。就是读取数据的时候会根据一定规则读取事务可见版本的数据可能是过期的数据不用加锁</p>
<p>快照读的实现方式undolog和多版本并发控制MVCC</p>
<p>使用快照读的场景:</p>
<ul>
<li>单纯的select操作不包括上述 select … lock in share mode、select … for update</li>
</ul>
<p>Read Committed隔离级别下快照读每次select都生成一个快照读</p>
<p>Read Repeatable隔离级别下快照读开启事务后第一个select语句才是快照读的地方而不是一开启事务就快照读</p>
<p>在 read-committed 隔离级别下,事务中的快照读,总是以最新的快照为基准进行查询的。</p>
<p>在 repeatable-read 隔离级别下,快照读是以事务开始时的快照为基准进行查询的,如果想以最新的快照为基准进行查询,可以先把事务提交完再进行查询。</p>
<p>在 repeatable-read 隔离级别下,别的事务在你生成快照后进行的删除、更新、新增,快照读是看不到的。</p>
<h3 id="_8">当前读<a class="headerlink" href="#_8" title="Permanent link">&para;</a></h3>
<p>当前读:读取的是最新版本, 并且对读取的记录加锁,保证其他事务不会再并发的修改这条记录,避免出现安全问题。</p>
<p>使用当前读的场景:</p>
<ul>
<li>select…lock in share mode (共享读锁)</li>
<li>select…for update</li>
<li>update</li>
<li>delete</li>
<li>insert</li>
</ul>
<p>当前读的实现方式next-key锁(行记录锁+Gap间隙锁)</p>
<p>间隙锁只有在Read Repeatable、Serializable隔离级别才有就是锁定范围空间的数据假设id有3,4,5锁定id&gt;3的数据是指的45及后面的数字都会被锁定因为此时如果不锁定没有的数据例如当加入了新的数据id=6就会出现幻读间隙锁避免了幻读。</p>
<p>1.对主键或唯一索引如果当前读时where条件全部精确命中(=或者in),这种场景本身就不会出现幻读,所以只会加行记录锁。</p>
<p>2.没有索引的列当前读操作时会加全表gap锁生产环境要注意。</p>
<p>3.非唯一索引列如果where条件部分命中(&gt;&lt;、like等)或者全未命中则会加附近Gap间隙锁。例如某表数据如下非唯一索引2,6,9,9,11,15。如下语句要操作非唯一索引列9的数据gap锁将会锁定的列是(6,11],该区间内无法插入数据。</p>
<p><a class="glightbox" href="https://static.cyub.vip/images/202010/next_key_lock.png" data-type="image" data-width="auto" data-height="auto" data-desc-position="bottom"><img alt="" src="https://static.cyub.vip/images/202010/next_key_lock.png" /></a></p>
<p>存储引擎层面的锁是为了最大程度的支持并发处理在InnoDB锁分行锁、Metadata Lock事务级表锁行锁的算法共有三种Record LockGap LockNext-Key Lock</p>
<p>Record Lock单个行记录的上锁
Gap Lock间歇锁不包含记录本身的区间锁
Next-Key Lock包含记录本身的区间锁
只有在RR隔离级别下才会有gap lock,next-key lock其中
当where条件为 普通索引时为gap lock或者Next-key Lock
当where条件为 主键索引的时候Next-key Lock 和Gap Lock的锁策略降级为行锁
当where条件 不是索引的时候innodb会给所有数据上锁然后返回Mysql server层然后在Server层过滤掉不符合条件的数据通过调用 unlock_row方法解锁</p>
<h3 id="_9">总结<a class="headerlink" href="#_9" title="Permanent link">&para;</a></h3>
<ol>
<li>不可重复读分为2部分:1.快照读 2.当前读</li>
<li><code>行锁+间隙锁</code>解决了当前读可能会导致的不可重复读的问题</li>
<li><code>mvcc+undo log</code>解决了快照读可能会导致的不可重复读的问题.</li>
<li>mysql的锁和mvcc的设计不单单解决了不可重复读的问题也解决了幻读的问题</li>
</ol>
<h2 id="_10">事务日志<a class="headerlink" href="#_10" title="Permanent link">&para;</a></h2>
<h2 id="_11">参考资料<a class="headerlink" href="#_11" title="Permanent link">&para;</a></h2>
<ul>
<li><a href="https://jin-yang.github.io/post/mysql-innodb-isolation-level.html">InnoDB隔离级别与实践</a></li>
<li><a href="https://www.cnblogs.com/codeclock/p/13689433.html">读快照实验</a></li>
<li><a href="https://blog.csdn.net/hello_world_cy/article/details/82109806">当前读实验</a></li>
<li><a href="https://blog.csdn.net/SnailMann/article/details/94724197?utm_medium=distribute.pc_aggpage_search_result.none-task-blog-2~all~first_rank_v2~rank_v25-1-94724197.nonecase&amp;utm_term=mysql%E5%BF%AB%E7%85%A7%E8%AF%BBundo&amp;spm=1000.2123.3001.4430">正确的理解MySQL的MVCC及实现原理</a></li>
<li><a href="https://blog.csdn.net/fuzhongmin05/article/details/91351933">InnoDB对MVCC的实现</a></li>
<li><a href="https://www.jianshu.com/p/4bcfffb27ed5">mysql日志系统之redo log和bin log</a></li>
<li><a href="https://www.cnblogs.com/f-ck-need-u/archive/2018/05/08/9010872.html">详细分析MySQL事务日志(redo log和undo log)</a></li>
<li><a href="http://blog.itpub.net/69912579/viewspace-2673644/">InnoDB 事务加锁分析</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/52977862">数据库基础Innodb MVCC实现原理</a></li>
<li><a href="https://zhuanlan.zhihu.com/p/40208895">MySQL InnoDB MVCC实现</a></li>
</ul>
<hr>
<div class="md-source-file">
<small>
最后更新:
<span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-iso_date">2023-10-11</span>
</small>
</div>
</article>
</div>
</div>
<button type="button" class="md-top md-icon" data-md-component="top" hidden>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8v12Z"/></svg>
回到页面顶部
</button>
</main>
<footer class="md-footer">
<nav class="md-footer__inner md-grid" aria-label="页脚" >
<a href="../%E7%AE%80%E4%BB%8B/" class="md-footer__link md-footer__link--prev" aria-label="上一页: 概览">
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M20 11v2H8l5.5 5.5-1.42 1.42L4.16 12l7.92-7.92L13.5 5.5 8 11h12Z"/></svg>
</div>
<div class="md-footer__title">
<span class="md-footer__direction">
上一页
</span>
<div class="md-ellipsis">
概览
</div>
</div>
</a>
<a href="../%E7%B4%A2%E5%BC%95/" class="md-footer__link md-footer__link--next" aria-label="下一页: 索引">
<div class="md-footer__title">
<span class="md-footer__direction">
下一页
</span>
<div class="md-ellipsis">
索引
</div>
</div>
<div class="md-footer__button md-icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M4 11v2h12l-5.5 5.5 1.42 1.42L19.84 12l-7.92-7.92L10.5 5.5 16 11H4Z"/></svg>
</div>
</a>
</nav>
<div class="md-footer-meta md-typeset">
<div class="md-footer-meta__inner md-grid">
<div class="md-copyright">
<div class="md-copyright__highlight">
Copyright &copy; 2023 - 2024 Tink
</div>
Made with
<a href="https://squidfunk.github.io/mkdocs-material/" target="_blank" rel="noopener">
Material for MkDocs
</a>
</div>
<div class="md-social">
<a href="https://github.com/squidfunk" target="_blank" rel="noopener" title="github.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
</a>
<a href="https://hub.docker.com/r/squidfunk/mkdocs-material/" target="_blank" rel="noopener" title="hub.docker.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M349.9 236.3h-66.1v-59.4h66.1v59.4zm0-204.3h-66.1v60.7h66.1V32zm78.2 144.8H362v59.4h66.1v-59.4zm-156.3-72.1h-66.1v60.1h66.1v-60.1zm78.1 0h-66.1v60.1h66.1v-60.1zm276.8 100c-14.4-9.7-47.6-13.2-73.1-8.4-3.3-24-16.7-44.9-41.1-63.7l-14-9.3-9.3 14c-18.4 27.8-23.4 73.6-3.7 103.8-8.7 4.7-25.8 11.1-48.4 10.7H2.4c-8.7 50.8 5.8 116.8 44 162.1 37.1 43.9 92.7 66.2 165.4 66.2 157.4 0 273.9-72.5 328.4-204.2 21.4.4 67.6.1 91.3-45.2 1.5-2.5 6.6-13.2 8.5-17.1l-13.3-8.9zm-511.1-27.9h-66v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm78.1 0h-66.1v59.4h66.1v-59.4zm-78.1-72.1h-66.1v60.1h66.1v-60.1z"/></svg>
</a>
<a href="https://pypi.org/project/mkdocs-material/" target="_blank" rel="noopener" title="pypi.org" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M439.8 200.5c-7.7-30.9-22.3-54.2-53.4-54.2h-40.1v47.4c0 36.8-31.2 67.8-66.8 67.8H172.7c-29.2 0-53.4 25-53.4 54.3v101.8c0 29 25.2 46 53.4 54.3 33.8 9.9 66.3 11.7 106.8 0 26.9-7.8 53.4-23.5 53.4-54.3v-40.7H226.2v-13.6h160.2c31.1 0 42.6-21.7 53.4-54.2 11.2-33.5 10.7-65.7 0-108.6zM286.2 404c11.1 0 20.1 9.1 20.1 20.3 0 11.3-9 20.4-20.1 20.4-11 0-20.1-9.2-20.1-20.4.1-11.3 9.1-20.3 20.1-20.3zM167.8 248.1h106.8c29.7 0 53.4-24.5 53.4-54.3V91.9c0-29-24.4-50.7-53.4-55.6-35.8-5.9-74.7-5.6-106.8.1-45.2 8-53.4 24.7-53.4 55.6v40.7h106.9v13.6h-147c-31.1 0-58.3 18.7-66.8 54.2-9.8 40.7-10.2 66.1 0 108.6 7.6 31.6 25.7 54.2 56.8 54.2H101v-48.8c0-35.3 30.5-66.4 66.8-66.4zm-6.7-142.6c-11.1 0-20.1-9.1-20.1-20.3.1-11.3 9-20.4 20.1-20.4 11 0 20.1 9.2 20.1 20.4s-9 20.3-20.1 20.3z"/></svg>
</a>
<a href="https://fosstodon.org/@squidfunk" target="_blank" rel="noopener me" title="fosstodon.org" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M433 179.11c0-97.2-63.71-125.7-63.71-125.7-62.52-28.7-228.56-28.4-290.48 0 0 0-63.72 28.5-63.72 125.7 0 115.7-6.6 259.4 105.63 289.1 40.51 10.7 75.32 13 103.33 11.4 50.81-2.8 79.32-18.1 79.32-18.1l-1.7-36.9s-36.31 11.4-77.12 10.1c-40.41-1.4-83-4.4-89.63-54a102.54 102.54 0 0 1-.9-13.9c85.63 20.9 158.65 9.1 178.75 6.7 56.12-6.7 105-41.3 111.23-72.9 9.8-49.8 9-121.5 9-121.5zm-75.12 125.2h-46.63v-114.2c0-49.7-64-51.6-64 6.9v62.5h-46.33V197c0-58.5-64-56.6-64-6.9v114.2H90.19c0-122.1-5.2-147.9 18.41-175 25.9-28.9 79.82-30.8 103.83 6.1l11.6 19.5 11.6-19.5c24.11-37.1 78.12-34.8 103.83-6.1 23.71 27.3 18.4 53 18.4 175z"/></svg>
</a>
<a href="https://twitter.com/squidfunk" target="_blank" rel="noopener" title="twitter.com" class="md-social__link">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Free 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2023 Fonticons, Inc.--><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
</a>
</div>
</div>
</div>
</footer>
</div>
<div class="md-dialog" data-md-component="dialog">
<div class="md-dialog__inner md-typeset"></div>
</div>
<script id="__config" type="application/json">{"base": "../../..", "features": ["announce.dismiss", "content.action.edit", "content.action.view", "content.code.annotate", "content.code.copy", "content.tooltips", "navigation.footer", "navigation.indexes", "navigation.sections", "navigation.tabs", "navigation.top", "navigation.tracking", "search.highlight", "search.share", "search.suggest", "toc.follow"], "search": "../../../assets/javascripts/workers/search.f886a092.min.js", "translations": {"clipboard.copied": "\u5df2\u590d\u5236", "clipboard.copy": "\u590d\u5236", "search.result.more.one": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.more.other": "\u5728\u8be5\u9875\u4e0a\u8fd8\u6709 # \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.none": "\u6ca1\u6709\u627e\u5230\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.one": "\u627e\u5230 1 \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.other": "# \u4e2a\u7b26\u5408\u6761\u4ef6\u7684\u7ed3\u679c", "search.result.placeholder": "\u952e\u5165\u4ee5\u5f00\u59cb\u641c\u7d22", "search.result.term.missing": "\u7f3a\u5c11", "select.version": "\u9009\u62e9\u5f53\u524d\u7248\u672c"}}</script>
<script src="../../../assets/javascripts/bundle.94c44541.min.js"></script>
<script src="../../../js/print-site.js"></script>
<script id="init-glightbox">const lightbox = GLightbox({"touchNavigation": true, "loop": false, "zoomable": true, "draggable": true, "openEffect": "zoom", "closeEffect": "zoom", "slideEffect": "slide"});
document$.subscribe(() => { lightbox.reload() });
</script></body>
</html>