数据库事务随记

ACID:数据库正确执行的四个基本要素的缩写
原子性(Atomicity)
一致性(Consistency)
隔离性(Isolation)
持久性(Durability)

事务的几种方式
单线程、排他锁(对同一单元的访问进行控制)、读写锁(读读场景时使用)、MVCC(Copy on Write,可以做到所有读是并行,写是串行的效果;也是最优的方案)
什么时候事务需要用到多线程?
内存:很快的动态开辟和消毁一块空间,IOPS很高
磁盘:IOPS低,将大量读写攒成一个batch去执行效率最高
内存的IOPS是磁盘的1000-10000倍(读算写)
在慢速设备(磁盘、网络)的场景下多线程和异步应用的很多;

事务调优:
    减少锁的覆盖范围
        Myisam表锁->Innodb行锁
        原位锁-MVCC多版本锁(重复读和读已提交)
    增加锁上可并行的线程数
        读写锁分离、允许并行读取数据
    选择正确锁类型
        悲观锁 发现已有锁,则切换(需要CPU开锁,内存页数据清掉,寄存器清掉)出去等待通知再进行争抢锁;适合并发争抢比较严重场景,假定会冲突时;
        乐观锁(自选锁) 发现已有锁,不进行切换出去,自旋主动轮询如发现已不被持有,则锁定;适合并发争抢不太严重的场景
        悲观和乐观的区别:悲观认为每次锁定的时间都比较大(wait和notifyAll的悲观场景,典型的悲观场景);乐观认为每次锁定的时间都不长,大部分乐观请求时都会成功,竞争并不激烈,假定不会冲突时。
事务单元之间的Happen-before关系
    读写
    写读
    读读
    写写
问题
    如何能够以最快的速度完成?
    又能保证上面四种操作的逻辑顺序

事务-排队法
    排队
        序列化读写
    优势
        不需要冲突控制
    劣势
        慢速设备
事务-排他锁
    针对同一个单元的访问进行访问控制(排他锁)
    对可能发生冲突的事务进行排他锁控制(同一队列)
    不会发生冲突的事务互不影响同时进行(多队列)
事务-读写锁
    针对读读场景可以优化
    对读读的场景完全可以进行并行操作;
    对读写、写读、写写场景下的操作进行串行(同一队列,序列化)
事务-MVCC
    本质就是copy on write
        能够做到写不阻塞读(在写的时候可以做到读,阻塞只出现在写写的操作)

多个事务,谁先谁后?
    MVCC把每次的写入,放到一个log里,读版本号为5的数据,先找版号为10的数据后,再向前找到版本号为5的数据,
    在不同的数据库里都在维护着一个数据的自增号(逻辑时间戳),每次写的时候都加1,如果在一个事务里有写读的话,写时也会自增。
    时间戳分为:1.逻辑时间戳(只保证先后顺序);2.物理时间戳(时间的顺序)
如何故障恢复?
    可能的错误情况
        业务属性不匹配,需要进行数据恢复(原子性)
            向smith转账100时,Bob账户不够100,需要进行回滚;记录下来事务之前操作的所有反向操作,在业务单元有问题的时候进行回滚;
        系统崩溃(DOWN机)
            对于进行了一半的事务,也是需要进行事务回滚的;对应数据库会进入recovery模式
碰到死锁了怎么办?
    死锁产生原因
        两个线程+不同方向+相同资源=死锁
    死锁的解决方案
        1.尽可能不死锁(降低隔离级别,不加读锁)
        2.碰撞检测(效率高)
        3.等锁超时
        *主流数据库的做法都是采用碰撞检测辅以等锁超时;
隔离性
    以性能为理由,对强一致性的破坏
序列化
    -排它锁
可重复读(REPEATABLE READ)
    *读写锁,读锁不能被写锁升级
        读读可并行
    幻象读(可重复读repeatable-read):A事务第一次读取时未有数据条数据的增减,第二次读取时已不是原来的数据条数,而是由B事务对数据的条数据有了增减(避免幻象读,则往往需要添加表级锁,其中Oracle使用多版本数据的方式实现)。
读已提交(READ COMMITTED) 同一事务里的两次读,可能会读到不同版本的数据;不可重复读
    *读写锁,读锁可被写锁升级
        读读并行
        读写并行(写读不可并行)
    (不可重复读)A事务中第一次读取更被修改过的数据a,第二次读取新的B事务已经提交的更改数据a(避免不可重复读,只需要对操作的数据添加行级锁即可)。
读未提交(READ UNCOMMITTED) 可能会读到写过程中未提交的数据
    *只加写锁,读不加锁
        读读并行
        读写并行
        写读并行
    (脏读)A事务读取B事务尚未提交的更改数据(脏读),并在此更改后的数据上进行操作,此时B事务回滚,那么A事务读到的数据根本是错误的。
快照隔离性(向四种场景映射)
    针对读多写少场景优化
    并行度能达到或超过读未提交,而隔离级别很高
    MVCC 快照读 核心思想是无锁编程(Copy on write)

写和写,有没有可能并行呢?

持久性
    事务完成以后,该事务对数据库所作的更改便持久的保存在数据库之中
But
    如何才能保证数据不丢呢?
        RAID保证持久性,RAID Controller保证两块磁盘的一致性-又是一个事务的概念(磁盘的方案)
        group commit组提交,如5次提交再落到磁盘上;
    IOPS和吞吐量是有翘翘板效应的

事务的调优原则
    减少锁的覆盖范围
        Myisam表锁->Innodb行锁
        原位锁->MVCC多版本(也是一个减少锁的覆盖范围问题)
    增加锁上可并行的线程数
        读锁写锁分离、允许并行读取数据
    选择正确锁类型
        悲观锁 适合并发争抢比较严重的场景
        乐观锁 适合并发争抢不太严重的场景

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值