单机事务

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/QinDaBao_/article/details/88353343

事务简介

事物的本质 => 锁和并发的结合体

优势:容易理解
劣势:性能一般

容易理解的模型性能不好,性能好的模型都不容易理解。

ACID保证事务完整性

bob给smith转1000元钱,要么钱在bob这,要么在smith这,不会让其他线程看到bob和smith的钱都为0的情况。

事务 - 单个事务单元

建立一个基于GMT_Modified的索引

读一行记录

写一行记录,同时更新这行记录的所有索引

删除整张表

插入,查询,更新,删除...

每一个操作都可以认为是一个事务。

事务 - 一组事务单元

事务单元之间需要等待需要操作的内容解锁之后,才能执行。

事务 - 产生的原因

事务单元之间的Happen-before关系

  • 读写
  • 读读
  • 写读
  • 写写

如何以最快的速度完成?又能保障顺序执行。

  • 序列化读写
    优势 - 不需要冲突控制
    劣势 - 慢速

  • 事务 - 排它锁

针对同一个单元的访问进行控制

两个事务单元如果没有冲突,就可以并行处理,并行。

如果两个事务单元共享数据,那就串行,加锁,只允许一个线程访问,则其他线程进不来。

  • 事务 - 读写锁
    写锁读锁分离开,读读并行,读写,写读,写写串行

可重复读:当这个数据读了之后,在锁没有释放的情况下,这次独到的数据,还是上一次的数据。

ACID的I一定意义的破坏了数据一致性,提升了运行速度、

事务 - MVCC

不是在原位写,本质是copy on write

实现了并发读,即写不阻塞读。

维持一个大事务,在运行它的时候,其他读的线程都在等待,导致慢速。

读写锁系统实现简单,MVCC实现复杂。

能够做到写不阻塞读

读 与 写 不错冲突,可以串行。

唯一需要并行的是写写。

并发度最好,系统实现的复杂度最高。

需要考虑的因素变多,

binlog需要维持多少,原来的老数据需要删掉。

事务处理常见问题

  • 多个事务,谁先谁后?

  • 如何故障恢复?

  • 碰到死锁了怎么办?

多个事务,谁先谁后?

数据库使用MVCC后,一定会遇到的问题。

一个读操作发生在一个写操作之后,那么版本号:读 > 写。

逻辑时间戳:
(本质是为了标记事务单元和另一个事务单元之间谁先谁后)
SCN(oracle) , Trx_id(Innodb)等等

故障恢复

可能出现的错误情况

1,业务属性不匹配
业务发现不允许继续执行下去,就需要回滚。
记录下来当前事务前面做的操作的反向操作,来恢复数据。

2,系统崩溃
系统故障恢复回来以后,事务的执行状态是只有一半的,
系统不能继续维持锁,因为线程都消失了,事务操作是水做的不知道了。
在数据库进行恢复的时候,事务只进行到中间一步时,需要做回滚操作。
在数据库回滚完成(recover)之前,外部应用是不能监听使用数据库的。

死锁和死锁检测

死锁产生原因

2个线程参与

不同方向

相同资源

例子:Bob给smith转账,同时,Smith给Bob转账

解决方案

尽可能不死锁

【死锁检测方法】碰撞检测:效率最高

【死锁检测方法】等锁超时:常见做法

事务 - ACID

原子性

要么都成功,要么都失败。

记录每执行一条之后的可以返回之前数据的undo sql语句,来保证了整个数据的可回归

一致性

can(happen before)

加锁,保证事务单元与实物单元之间的顺序化

一个事务单元完全完成,才对外可见

如果事务单元之间串行,那么一定是一致性的,但是并发就很差了。

隔离性

以性能为理由,对一致性的破坏

SQL 92 标准定义的隔离性

隔离界别

  • (一)序列化读写
    排它锁

单位时间内只能有一个人进来

性能差,意味着这个系统不可用

  • (二)读写锁
  1. 可重复读

读锁不能被写锁升级

读读可并行,其他情况要串行

  1. 读已提交

可以将读锁升级

实现了:读读并行 读写并行(写读不能)

  1. 读未提交
    只加写锁,读不加锁

实现了:
读读并行
读写并行
写渎并行

系统变成了,全部写串行,读操作并行

问题:可能读到写过程中的数据

隔离级别扩展

快照隔离级别

Copy on write 无锁编程

多版本并发控制

事务的ACID

原子性
一致性

  • 隔离性(扩展:MVCC/SNAPSHOt ISOLATION)
  • 持久性(扩展:持久性保证策略)
  1. 单机事务的典型异常应对策略

  2. 事务的调优原则

隔离性

快照隔离性

事务版本,有回滚版本。

读未提交的隔离界别 => 因为读没有加锁,可能会出现读到其他事务单元的中间状态、

快照读 能在读到 ** 一致性 ** 的同时实现读未提交

系统会把 快照读映射到序列化读,因为sql92标准本身有问题不完善。
所以就把快照读映射到读未提交,读已提交上面去。

事物的定义滞后于事务的发展

分布式系统会使用新的隔离界别和方法,业务应用的发展已经远远超过传统意义对事物的定义。

以上都是针对读和写的事务和优化,写和写能实现并行么?

持久性

为什么在数据库有实物这个概念,
事务将多个不同的命令组装出成一个事务单元。

记日志,保证每一次的curd操作不丢失,导致速度降低,降低并发度。

每一次的写,要能够保证持久性。

定义:

事务完成以后,钙食物对数据库所做的更改便持久的保存在数据库之中。

如何保证数据不丢

丢失数据的可能性

  1. 物理磁盘损坏(RAID的持久性)
  2. 如果不是每次写操作,都到磁盘,数据运行在内存,掉电之后数据丢失
    但如果每次commit都要fsync都要写到磁盘,就会降低速度

解决方法

一份数据写到两个磁盘

需要保证写操作同时成功,或者同时失败

RAID的持久性

1.提交请求到内存就返回(不可靠)
2.将内存的数据打包到磁盘(定期打包,提升系统吞吐量)

核心目的:提升并行度
在计算机世界非常常见。

补充

tps是个并发指标
脏读的概念

单机事务典型异常应对策略

  • 回滚

  • 系统down机

Bob给Smith100元的数据库事务

lock bob and Smith 上锁

ver 1: Bob有100元 ,Smith有0元 查询bob有没有钱
ver 2: Bob有0元 ,Smith有0元 把Bob钱减掉
ver 3: Bob有0元 ,Smith有100元 把smith钱加上

Unlock bob and Smith 解锁

重启后进入recovery模式

提交后十五单元继续完成提交

未提交事务单元回滚

之后才提供外界访问,recovery体现了原子性。

为了防止recovery时候挂机,
recovery模式在读取事务执行过程中记得undo回滚日志时,也需要记录日志

事务调优原则

在不影响业务应用的前提下

  1. 减少锁的覆盖范围

myisam表锁 -> innodb 行锁
原位锁 -> MVCC

  1. 增加锁上并行的线程数

读锁写锁分离,允许并行读取数据
多线程并行读取

  1. 选择正确的所的类型
    悲观锁
    使线程到blocking状态,通知消息ok的状态切换回等待状态
    适合并发症强比较严重的场景
    乐观锁
    适合并发症强比较不严重的场景

悲观锁,乐观锁,原位锁,排他锁,艘可以是读锁或写锁。

猜你喜欢

转载自blog.csdn.net/QinDaBao_/article/details/88353343
今日推荐