1.数据库事务的特征

1.1事务的四大特征ACID

原子性Atomicity:对数据库的一系列操作,要么全成功,要么全失败。如果前面的操作成功了,后面的失败了,就必须回滚。
隔离性 Isolation:不同事务之间是透明的,不会相互干扰。
持久性 Durability:对数据库的操作,只要事务提交成功,那么结果就是永久性的,这个与InnoDB的崩溃恢复逻辑(crash-safe)密切相关。持久性是通过redo log和双写缓冲实现的。
原子性,隔离性和持久性都是为了实现一致性。
一致性 consistent,指的是数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。

1.2 事务的隔离级别


修改或者删除造成的读取不一致叫做不可重复读,插入造成的读不一致叫幻读。

1.3 数据库什么时候出现事务问题

当执行一条更新语句时,有事务吗?
其实是有的,它不仅自动开启了一个事务,还自动提交了,并最终落盘。这也是开启事务的第一种方式。
增删改都会自动提交事务,当然是一条SQl事务。事实上,每个事务都有编号的,这个编号是一个整数,有递增的特征。
如果要把多条SQL放在一个事务里,就要手动开启事务。手动开启事务有两种方式,一种是用begin,一种是用start transaction。
如何结束事务呢?也有两种方式,第一种是回滚事务rollback,一种是提交commit。

InnoDB里有一个autocommit参数,可以控制是否自动提交。

3.如何解决读一致性问题

首先注意,读一致性只是保证看到第一次查询时看到的数据版本,保证本次事务能顺利完成,而不一定是数据库最新的内容,有两大方案LVCC和MVCC。
如果要保证前后两次读取数据一致,那么我读取的时候,锁定要操作的数据,不允许其他事务修改就行了。这种方案叫基于锁的并发控制 LBCC。
这样做的坏处是读取的时候也不允许修改,这意味着不支持并发的读写操作,而我们大多数应用都是读多写少的,这极大影响了效率。
另外一个方案是在修改数据之前给它建立一个备份或者快照,后面再来读取快照就行了,这种方案叫做多版本的并发控制 MVCC。

3.1 MVCC实现原理

一个事务能看到的数据版本:1.第一次查询之前已经提交的事务和修改;2.本事务的修改
一个事务不能看到的数据版本:本事务第一次查询之后创建的事务(事务ID比我的事务ID大)和活跃未提交的事务的修改。
MVCC能够达到的效果就是:我可以查到我这个事务开始之前已经存在的数据,即使它在后面被修改或者删除了。而我这个事务之后新增的数据,我是查不到的。所以我们才把这个叫做快照。不管别的事务做任何增删改查的操作,它只能看到第一次查询时看到的数据版本。
InnoDB的事务都是有编号的,而且会不断递增。InnoDB为每行记录都实现了两个隐藏字段:
DB_TRX_ID,6字节:事务ID,数据是在哪个事务插入或者修改为新数据的,就记录为当前事务ID。
DB_ROLL_PTR,7字节,回滚指针,可以理解为删除版本号,数据被删除或记录为旧数据的时候,记录当前事务ID,没有修改或者删除的时候是空。

查找的规则是:只能查找创建时间小于等于当前事务ID的数据,和删除时间大于当前事务ID的行。也就是说这里其实就是定了一种规则起到临时快照的作用,保证某个事物拿到它应该拿到的事务,而不一定是最新的事务。

在InnoDB中,一条数据的旧版本是存在undo log中,修改多次的时候,这些undo log会形成一个链条,叫做undo log链,所以前面说的DB_ROLL_PTR,其实就是指向undo log链的指针。

另一个问题,不同的事务执行查询的时候,都去undo log 链查找数据的时候,拿到的数据是不一样的,一个事务该如何判断应该读取哪个版本的数据呢?

为了满足本节开头说的规则,我们需要一个数据结构,把本事务ID,活跃事务ID,当前系统最大事务ID存起来方便判断,这个数据结构就是Read View(可见性视图),每个视图都维护一个自己的Read View。

m_ids:表示在生成ReadView时当前系统中活跃的读写事务的事务ID列表,我的理解是当前还没有提交的事务。
min_trx_id:表示在生成ReadView时当前系统中活跃的读写事务中最小事务的id,也就是m_ids中的最小值。
max_trx_id:表示生成ReadView时系统中应该分配给下一个事务的ID值。
creator_trx_id:表示生成该ReadView的事务的事务ID。

这个执行过程比较复杂https://www.jianshu.com/p/8845ddca3b23,但是我们抓住几个原则就明确了;
1.如果数据版本的trx_id=creator_trx_id,是本事务修改的,可以访问
2.如果数据的trx_id<min_trx_id,那么表明修改数据的事务在创建第一次快照的时候已经提交了,可见。
3.如果数据的trx_id>=max_trx_id,那么表明修改数据的事务是在第一次快照之后修改提交的,不可见。
4.如果数据版本的trx_id在min_trx_id和max_trx_id之间,看看是否在m_ids中,如果在,说明在创建快照时还没有提交,不可见。反之则可以。
5.如果当前版本不可见,就找undo log 链中的下一个版本。

另外一点,RR中的ReadView是事务第一次查询的时候创建的,而RC的ReadView是事务每次查询的时候创建的。

4.数据库的锁

和Java里面的一样,锁是为了解决资源竞争的问题,Java里的资源是对象,数据库的资源就是数据表或者数据行。
锁要实现资源竞争与效率的平衡,因此针对数据库的特殊情况,这些锁有明显的数据库特征。

从不同的角度可以分为多类:
1.从锁的范围来看“
表级锁

行级别的锁又分为共享锁和排它锁。
表级别的锁是两种意向锁

锁的算法:记录锁,间隙锁和临键锁

自增锁:
一种特殊的表锁,用来防止自增字段重复,数据插入以后就会释放,而不需要等到事务提交才释放,这样可以让其他事务执行插入时能能快的获得可以使用的自增值。
意向锁
意向锁是针对表的,更像一个标识,用来判断一个表是否被加锁了,如果有则加锁 ,否则直接返回失败。为什么要这样呢?假如我们要给一个表加表锁,必须先全表扫描是否有锁,才能执行加锁,代价比较高。而意向锁就像火车卫生间的指示灯一样,只有根据标识就可以直接处理了。
插入意向锁:是一种特殊的间隙锁,间隙锁不允许插入数据,但是插入意向锁允许多个事务同时插入数据到一个范围,例如间隙是(4,7),一个事务插入5,一个事务插入6,此时不会发生锁等待。

5.锁的算法

记录锁,间隙锁和临键锁,其实就是通过锁索引来锁定某个特定的元素或者区间。
记录锁:当我们对于唯一性的索引(包括唯一索引和主键索引)使用等值查询,精准匹配到一条记录的时候,使用的就是记录锁。
间隙锁:当查询不存在的时候, 不论用等值还是范围查询,用的都是间隙锁。间隙锁主要目的是阻塞插入insert,不同间隙锁之间不冲突。
临键锁:我们使用范围查询,不仅命中记录,还包括了Gap间隙,这时候使用的就是临键锁。就相当于记录锁+间隙锁。如果是唯一性索引等值匹配到一条记录就退化成了记录锁。没有匹配到任何记录的时候,退化成了间隙锁。

临建锁锁的是一个左开右闭的区间,例如上图锁7的时候会将(4,7]和[7,10)都给锁定,这样可以防止出现幻读。

6.隔离级别的实现

根据上述分析,我们可以总结四种隔离级别的实现方法

6.1 Read Uncommitted

不加锁

6.2 Serializable

所有的select 语句都隐式转换为select in share mode,会和update ,delete 互斥。

6.3 Repeatable Read

RR级别下,普通的读使用快照读,底层使用MVCC来实现。
加锁的select(包括共享和排它锁) 以及更新操作update,delete 等语句使用当前读,底层使用记录锁,间隙锁或者临键锁。

6.4 Read Commited

RC隔离级别下,普通的select 都是快照读,使用MVCC实现。
加锁的select都是用记录锁,没有gap lock。所以会出现幻读的情况。
除了两种特殊情况,外键约束检查以及重复键检查时,会使用间隙锁封锁区间。

数据库系列7:事务与锁的实现原理相关推荐

  1. mysql服务器级别角色_服务器数据库系列 - MySQL事务隔离级别详解

    作者:xm_king SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的.低级别的隔离级一般支持更高的并发处理,并拥有更低的系统开销. Read Un ...

  2. mysql 事务 不同库_MYSQL数据库重点:事务与锁机制

    一.事务 一组连续的数据库操作,每一次操作都成功,整个事务就成功,只要有一步出错,整个事务就失败: MySQL事务与存储引擎相关 1.MyISAM:不支持事务,用于只读程序提高性能 2.InnoDB: ...

  3. 同时更改一条数据_数据库中的引擎、事务、锁、MVCC(二)

    二.事务 介绍锁之前,咱们先介绍一下 什么叫做事务. 事务就是一组对数据库的一系列的操作,要么同时成功,要么同时失败. 1.事务的特性(ACID): 原子性:事务是整个操作,不可分割,要么都成功,要么 ...

  4. Redis数据库系列(四)、Redis事务、乐观锁和分布式锁

    第四章.Redis事务.乐观锁和分布式锁 什么是事务机制? 4.1.关系型数据库中的事务机制遵循ACID规则 关系型数据库例如MySql.Oracle: 事务的英文是transaction,以现实中的 ...

  5. 数据库事务与锁(一)——事务的简单介绍

    前言 最近系统上线了,这两天收到反馈,操作按钮动不了了.删除按钮动不了了等等类似的问题,仔细查看日志错误,提示:Lock wait timeout exceeded; try restarting t ...

  6. 大白话关系型数据库:索引,事务,锁

    感谢阅读.也欢迎大家可以去看<MySQL技术内幕>和橘黄色的<算法>. 前言 数据库是软件开发的核心,因为一个软件如果要有状态,也就是它记得你什么时候操作过什么,那么数据要持久 ...

  7. Redis 学习笔记-NoSQL数据库 常用五大数据类型 Redis配置文件介绍 Redis的发布和订阅 Redis_事务_锁机制_秒杀 Redis应用问题解决 分布式锁

    1.NoSQL数据库 1.1 NoSQL数据库概述 NoSQL(NosQL = Not Only sQL ),意即"不仅仅是sQL",泛指非关系型的数据库.NoSQL不依赖业务逻辑 ...

  8. mysql乐观锁与事务_[数据库事务与锁]详解七: 深入理解乐观锁与悲观锁

    注明: 本文转载自http://www.hollischuang.com/archives/934 在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库 ...

  9. 数据库语言SQL:事务,锁,索引

    目录 1. 事务 1.1 事务的作用 1.2 提交事务 1.3 事务的状态和性质(原子,一致,隔离,持久) 2. 锁 2.1 锁的机制 2.2 常见锁举例 2.3 锁等待和死锁 2.4 锁争用 3. ...

最新文章

  1. 支付宝,马云其人与我们的心态
  2. mvc html的扩展,关于asp.net mvc 3:Razor无法正确呈现HtmlHelper扩展方法
  3. 把价钱转化为xx.xx的形式
  4. python学习-日志(logging的定义、参数、format、示例代码、创建logging对象、设置Handler)
  5. js (javascript) 中获取年月日信息
  6. soapui 测试soap_使用SoapUI调用不同的安全WCF SOAP服务-基本身份验证,第二部分
  7. idea断点_IDEA Debug 无法进入断点的解决方法
  8. IBM收购数据库安全公司 围剿Oracle之心不死
  9. 多语言 获取当前语言
  10. SysTick_Handler cortex-m0 LPC1114
  11. .NET Compact Framework 多线程下的等待事件
  12. 华为效仿苹果卖高价手机?滴滴顺风车开放灰度测试;苹果官微被投诉“攻陷”| 极客头条...
  13. 不混淆 android jni,JNI 防混淆 Android proguard
  14. Win10PE启动维护工具 | U盘WinPE下载
  15. 【论文】(COPRA)Finding overlapping communities in networks by label propagation
  16. 神经网络的原理和应用,神经网络理论及应用
  17. shell遍历ip执行特定功能
  18. 好用的BUG、内存泄露捕捉工具 EurekaLog v6.0.3 Enterprise For D5-D2007
  19. 用python完成一个数独小游戏
  20. 微信公众号开发,移动端开发遇到的问题及其他技巧

热门文章

  1. 我的世界java1.13下_Minecraft我的世界Java版1.13-pre3更新内容
  2. ak sk认证java demo_AK-SK鉴权
  3. 解读小米模式:颠覆式创新者的背后
  4. 广东高考成绩及录取分数线揭晓
  5. html创建电子邮件链接教程
  6. 03 - JS数据类型转换/判断相等
  7. HTML DOM属性和方法
  8. python解压zip文件_python怎样压缩和解压缩ZIP文件(转)
  9. 开源h5游戏 宠物_释放:宠物和动物的开源技术
  10. “eclipse在编译代码时运行结果始终是之前程序的结果”如何解决?