博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MySQL事务和隔离级别
阅读量:3947 次
发布时间:2019-05-24

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

事务

  1. 基本概念

    是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。

  2. 和程序比较:

    在关系数据库中,一个事务可以是一条或多条SQL语句,也可以包含一个或多个程序。
    一个程序通常包含多个事务。

  3. 事务的特性(ACID)

  • 原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做;
  • 一致性(consistency):事务必须使数据库从一个一致性状态变成另一个一致性状态;
  • 隔离性(isolation):一个事务的执行不能被其他事务干扰;
  • 持续性(durability):也称永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

并发控制

多用户数据库:允许多个用户同时使用的数据库(订票系统)

不同的多事务执行方式:

  1. 串行执行:每个时刻只有一个事务运行,其他事务必须等到这个事务结束后方能运行。
  2. 交叉并发方式:
    单处理机系统中,事务的并发执行实际上是这些并行事务的并行操作轮流交叉运行(不是真正的并发,但是提高了系统效率)
  3. 同时并发方式:
    多处理机系统中,每个处理机可以运行一个事务,多个处理机可以同时运行多个事务,实现多个事务真正的并行运行

并发执行带来的问题:

  • 多个事务同时存取同一数据(共享资源)
  • 存取不正确的数据,破坏事务一致性和数据库一致性
并发控制概述

并发操作带来的数据不一致性包括

  • 丢失修改(lost update)
    T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。
  • 读脏数据(dirty read)
    T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。
  • 不可重复读(non-repeatable read)
    T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。
  • 幻影读
    T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和和第一次读取的结果不同。

记号:W(x)写数据x R(x)读数据x

并发控制机制的任务:

  • 对并发操作进行正确的调度
  • 保证事务的隔离性
  • 保证数据库的一致性

并发控制的主要技术

  • 封锁(locking)(主要使用的)
  • 时间戳(timestamp)
  • 乐观控制法(optimistic scheduler)
  • 多版本并发控制(multi-version concurrency control ,MVCC)
封锁

封锁:封锁就是事务T在对某个数据对象(例如表、记录等)操作之前,先向系统发出请求,对其加锁。加锁后事务T就对该数据对象有了一定的控制,在事务T释放它的锁之前,其它的事务不能更新此数据对象

确切的控制由封锁的类型决定

读写锁:

排它锁(X锁,exclusive locks)、共享锁(S 锁,share locks)

排它锁又称写锁,对A加了排它锁之后,其他事务不能对A加 任何类型的锁(排斥读和写)

共享锁又称读锁,对A加了共享锁之后,其他事务只能对A加S锁,不能加X锁(只排斥写)
在这里插入图片描述

意向锁:

Innodb的意向锁主要用户多粒度的锁并存的情况。比如事务A要在一个表上加S锁,如果表中的一行已被事务B加了X锁,那么该锁的申请也应被阻塞。如果表中的数据很多,逐行检查锁标志的开销将很大,系统的性能将会受到影响。为了解决这个问题,可以在表级上引入新的锁类型来表示其所属行的加锁情况,这就引出了“意向锁”的概念。

举个例子,如果表中记录1亿,事务A把其中有几条记录上了行锁了,这时事务B需要给这个表加表级锁,如果没有意向锁的话,那就要去表中查找这一亿条记录是否上锁了。如果存在意向锁,那么假如事务A在更新一条记录之前,先加意向锁,再加X锁,事务B先检查该表上是否存在意向锁,存在的意向锁是否与自己准备加的锁冲突,如果有冲突,则等待直到事务A释放,而无须逐条记录去检测。事务B更新表时,其实无须知道到底哪一行被锁了,它只要知道反正有一行被锁了就行了。
说白了意向锁的主要作用是处理行锁和表锁之间的矛盾,能够显示“某个事务正在某一行上持有了锁,或者准备去持有锁”。
在这里插入图片描述

封锁协议

在运用X锁和S锁对数据对象加锁时,需要约定一些规则:封锁协议(Locking Protocol)

何时申请X锁或S锁
持锁时间、何时释放

对封锁方式制定不同的规则,就形成了各种不同的封锁协议。

常用的封锁协议:三级封锁协议、 两段锁协议
三级封锁协议在不同程度上解决了并发问题,为并发操作的正确调度提供一定的保证。

三级封锁协议

1、一级封锁协议

事务T在修改数据R之前,必须先对其加X锁,直到事务结束(commit/rollback)才释放。
一级封锁协议可以防止丢失修改
如果是读数据,不需要加锁的,所以它不能保证可重复读和不读“脏”数据。
在这里插入图片描述
在这里插入图片描述

2、 二级封锁协议

在一级封锁协议的基础(写要加X锁,事务结束释放)上,增加事务T在读入数据R之前必须先对其加S锁,读完后即可释放S锁。(读要加S锁,读完即释放)
二级封锁协议除了可以防止丢失修改,还可以防止读脏数据
由于读完数据即释放S锁,不能保证不可重复读
在这里插入图片描述
在这里插入图片描述

3、三级封锁协议:

在一级封锁协议基础上增加事务T在读取数据R之前必须先对其加S锁,直到事务结束后释放。
三级封锁协议除了可以防止丢失修改和读脏数据外,还防止了不可重复读。
在这里插入图片描述
三级封锁协议的主要区别是什么操作需要申请锁,何时释放锁。封锁协议越高,一致性程度越高。

在这里插入图片描述

两段锁协议

加锁和解锁分为两个阶段进行。在事务执行过程中,随时都可以锁定,锁只有在执行commit或rollback时才会释放,并且所有的锁都是在同一时刻被释放。

MySQL 的 InnoDB 存储引擎采用两段锁协议,会根据隔离级别在需要的时候自动加锁,并且所有的锁都是在同一时刻被释放,这被称为隐式锁定。

在这里插入图片描述

隔离级别

脏读"、“不可重复读"和"幻读”,其实都是数据库读一致性问题,必须由数据库提供一定的事务隔离机制来解决。

数据库的事务隔离越严格,并发副作用越小,但付出的代价也就越大。

MYSQL常看当前数据库的事务隔离级别:show variables like ‘tx_isolation’;

1、读未提交 (Read Uncommitted)

最低的隔离等级,允许其他事务看到没有提交的数据,会导致脏读。

2、读已提交 (Read Committed)

被读取的数据可以被其他事务修改,这样可能导致不可重复读。也就是说一个事务所做的修改在提交之前对其它事务是不可见的。该等级也是 SQL Server 默认的隔离等级。

3、可重复读(Repeatable Read)

一个事务中多次读取相同的记录,结果是一致的,可避免脏读、不可重复读。

MYSQL默认是REPEATABLE-READ 。

4、串行化(Serializable)

所有事务一个接着一个的执行,这样可以避免幻读 (phantom read),对于基于锁来实现并发控制的数据库来说,串行化要求在执行范围查询的时候,需要获取范围锁,如果不是基于锁实现并发控制的数据库,则检查到有违反串行操作的事务时,需回滚该事务。

5、总结

读未提交: 一个事务还没提交时,它做的变更就能被别的事务看到。
读提交: 一个事务提交之后,它做的变更才会被其他事务看到。
可重复读 : 一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。
串行化: 顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。
四个级别逐渐增强,每个级别解决一个问题,事务级别越高,性能越差,大多数环境(Read committed 就可以用了)

隔离级别 读数据一致性 脏读 不可重复读 幻影读
未提交读 最低级别
提交读 语句级 ×
可重复读 事务级 × ×
可串行化 最高级别 × × ×

事务隔离级别的实现

  • 读未提交 无锁

  • 读已提交 MVCC(Multi-Version Concurrency Control, MVCC)多版本并发控制

  • 可重复读

    MVCC只工作在REPEATABLE READ和READ COMMITED隔离级别下。
    MVCC最大的作用是: 实现了非阻塞的读操作,写操作也只锁定了必要的行.

  • 可序列化 读加共享锁,写加排他锁,读写互斥。使用的悲观锁的理论。

参考:

  • 《MySQL技术内幕:InnoDB存储引擎》

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

你可能感兴趣的文章
ListView的使用
查看>>
Android动画机制总结
查看>>
NDK开发总结
查看>>
设计模式之创建型模式
查看>>
设计模式之结构型模式
查看>>
设计模式之行为模式
查看>>
Java内存区域和内存溢出异常
查看>>
Java内存分配及垃圾回收
查看>>
Java并发编程学习——对象的共享
查看>>
Java并发编程学习——对象的组合
查看>>
Java并发编程学习——基础构建模块
查看>>
看懂UML类图和时序图
查看>>
UML 基础: 类图(转自IBM开发者社区)
查看>>
工作感悟(2017/3/26)
查看>>
Spring Data Elasticsearch 配置 LocalDate、LocalDateTime 反序列化
查看>>
Yew 初尝试
查看>>
Rust SSH 操作 执行远程命令 上传下载文件
查看>>
浅谈GCD
查看>>
IOS控件之UITextField用法及注意点
查看>>
IOS控件之UITableView使用技巧
查看>>