博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[高性能MySQL] 第1章 MySQL架构与历史
阅读量:2341 次
发布时间:2019-05-10

本文共 2262 字,大约阅读时间需要 7 分钟。

事务

ACID

1. 原子性(Atomicity)

事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。

回滚可以用回滚日志来实现,回滚日志记录着事务所执行的修改操作,在回滚时反向执行这些修改操作即可。

2. 一致性(Consistency)

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。

3. 隔离性(Isolation)

一个事务所做的修改在最终提交以前,对其它事务是不可见的。

4. 持久性(Durability)

一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

使用重做日志来保证持久性。


隔离级别

  • 脏读:事务可以读取未提交的数据
  • 不可重复读:同一个事务内,两次执行同样的查询,可能得到不一样的结果
  • 幻读:当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。

1. 未提交读(READ UNCOMMITTED)

事务中的修改,即使没有提交,对其它事务也是可见的。

2. 提交读(READ COMMITTED)

一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。

3. 可重复读(REPEATABLE READ)

保证在同一个事务中多次读取同样数据的结果是一样的。

4. 可串行化(SERIALIZABLE)

强制事务串行执行。在读取的每行数据上都加锁

隔离级别 脏读 不可重复读 幻影读 加锁读
未提交读 ×
提交读 × ×
可重复读 × × ×
可串行化 × × ×

多版本并发控制

多版本并发控制(Multi-Version Concurrency Control, MVCC)是 MySQL 的 InnoDB 存储引擎实现隔离级别的一种具体方式,用于实现提交读和可重复读这两种隔离级别。而未提交读隔离级别总是读取最新的数据行,无需使用 MVCC。可串行化隔离级别需要对所有读取的行都加锁,单纯使用 MVCC 无法实现。

MVCC 在每行记录后面都保存着两个隐藏的列,用来存储两个版本号:

  • 创建版本号:指示创建一个数据行的快照时的系统版本号;
  • 删除版本号:如果该快照的删除版本号大于当前事务版本号表示该快照有效,否则表示该快照已经被删除了。

实现过程:

1. SELECT

多个事务必须读取到同一个数据行的快照,并且这个快照是距离现在最近的一个有效快照。但是也有例外,如果有一个事务正在修改该数据行,那么它可以读取事务本身所做的修改,而不用和其它事务的读取结果一致。

把没有对一个数据行做修改的事务称为 T,T 所要读取的数据行快照的创建版本号必须小于 T 的版本号,因为如果大于或者等于 T 的版本号,那么表示该数据行快照是其它事务的最新修改,因此不能去读取它。除此之外,T 所要读取的数据行快照的删除版本号必须大于 T 的版本号,因为如果小于等于 T 的版本号,那么表示该数据行快照是已经被删除的,不应该去读取它。

2. INSERT

将当前系统版本号作为数据行快照的创建版本号。

3. DELETE

将当前系统版本号作为数据行快照的删除版本号。

4. UPDATE

将当前系统版本号作为更新前的数据行快照的删除版本号,并将当前系统版本号作为更新后的数据行快照的创建版本号。可以理解为先执行 DELETE 后执行 INSERT。


Next-Key Locks

Next-Key Locks 是 MySQL 的 InnoDB 存储引擎的一种锁实现。

MVCC 不能解决幻读的问题,Next-Key Locks 就是为了解决这个问题而存在的。在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。

  • Record Locks:锁定一个记录上的索引,而不是记录本身。如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。

  • Gap Locks:锁定索引之间的间隙,但是不包含索引本身。

  • Next-Key Locks:它是 Record Locks 和 Gap Locks 的结合,不仅锁定一个记录上的索引,也锁定索引之间的间隙。例如一个索引包含以下值:10, 11, 13, and 20,那么就需要锁定以下区间:

(negative infinity, 10](10, 11](11, 13](13, 20](20, positive infinity)

事务在加锁时有多种方式:

一次性锁协议,事务开始时,即一次性申请所有的锁,之后不会再申请任何锁,如果其中某个锁不可用,则整个申请就不成功,事务就不会执行,在事务尾端,一次性释放所有的锁。一次性锁协议不会产生死锁的问题,但事务的并发度不高。

两阶段锁协议,整个事务分为两个阶段,前一个阶段为加锁,后一个阶段为解锁。在加锁阶段,事务只能加锁,也可以操作数据,但不能解锁,直到事务释放第一个锁,就进入解锁阶段,此过程中事务只能解锁,也可以操作数据,不能再加锁。两阶段锁协议使得事务具有较高的并发度,因为解锁不必发生在事务结尾。它的不足是没有解决死锁的问题,因为它在加锁阶段没有顺序要求。如两个事务分别申请了A, B锁,接着又申请对方的锁,此时进入死锁状态。

转载地址:http://cmkvb.baihongyu.com/

你可能感兴趣的文章
oracle定时删除表空间的数据并释放表空间
查看>>
servlet文件上传下载
查看>>
解决文件提示: /bin/ksh^M: bad interpreter: bad interpreter:No such file or directory
查看>>
ajaxanywhere jsp 使用
查看>>
jquery的使用
查看>>
如何静态化JSP页面
查看>>
XML 与 Java 技术: 用 Castor 进行数据绑定
查看>>
Python未知领域系列:(附Python学习教程+Python学习路线)Python高级教程之面向对象
查看>>
盘点Python 面向对象编程最容易被忽视的知识点
查看>>
Python:一个可以套路别人的python小程序
查看>>
用Python告诉你:这些年,我们点过的的那些外卖
查看>>
如何美观地打印Python对象?这个标准库可以简单实现
查看>>
写作路上的这些小成绩,铸就了一个不平庸的程序员
查看>>
程序员找工作的个人经验教训以及注意事项
查看>>
2019 编程语言排行榜:Java、Python 龙争虎斗!谁又屹立不倒
查看>>
拥有10年编程经验的你,为什么还一直停留在原地
查看>>
Flask vs Django,Python Web开发用哪个框架更好
查看>>
用Python制作动态二维码,一行代码就做到了
查看>>
Python说:常见的数据分析库有哪些
查看>>
Python教程:Python数据类型之字典
查看>>