• 数据库事务


    数据库事务的四大属性

    原子性,Atomicity,

    意味着我们对数据库的一系列的操作,要么都是成功,要么都是失败,不可能
    出现部分成功或者部分失败的情况。
    思考:都成功很容易保证。在前面的操作已经成功了的情况下,后面的操作失败了,怎么保证全部
    原子性,在 InnoDB 里面是通过 undo log 来实现的。
    undo log(撤销日志或回滚日志)记录了事务发生之前的数据状态(不包括 select),在发生异常
    执行 undo 的时候,仅仅是将数据从逻辑上恢复至事务之前的状态(回滚),而不是从物理页面上操作实现的,属于逻辑格式的日志。

    隔离性,isolation,

    有了事务的定义以后,在数据库里面会有很多的事务同时去操作我们的同一张表或者同一行数据,必然会产生一些并发或者干扰的操作,对隔离性就是这些很多个的事务,对表或者
    行的并发操作,应该是透明的,互相不干扰的。通过这种方式,我们最终也是保证业务数据的一致性。

    持久性,Durable,

    我们对数据库的任意的操作,增删改,只要事务提交成功,那么结果就是永久性
    的,不可能因为我们重启了数据库的服务器,它又恢复到原来的状态了。
     

    一致性,Consistent, 由上面的三大特性保证

    指的是数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。比如主键必须是唯一的,字段长度符合要求。另一方面是用户自定义的完整性。
    比如转账,A 账户余额减少 1000,B 账户余额只增加了 500,这个时候因为两个操作都成功了,按
    照我们对原子性的定义,它是满足原子性的, 但是它没有满足一致性,因为它导致了会计科目的不平衡。还有一种情况,A 账户余额为 0,如果这个时候转账成功了,A 账户的余额会变成-1000,虽然它满足了原子性的,但是我们知道,借记卡的余额是不能够小于 0 的,所以也违反了一致性。

    事物的四大特性原子性、持久性、一致性都是怎么实现的?

      原子性:当事务执行时,先记录undolog,undolog记录的是操作前的值,随后记录redolog,redolog记录的是操作后的值,当未提交事务时发生宕机,先执行redolog,把值更新成操作后的值,最后执行undolog,把值更新回最初的值,从而保证事务的执行状态一致。

      隔离性:lbcc,在数据操作时有对应的锁进行并发控制,脏读由排它锁,不可重复读由共享锁解决,幻读由临建锁解决,因此保证事务的之间的隔离

      持久性:数据修改时会写入redolog,即使宕机数据也能从redolog中恢复修改的数据。实现了数据的持久化

      一致性:上述三大特性最终保证了数据的一致性。

    事物的并发带来的问题:

    在一个事务里面,由于其他的时候修改了数据并且没有提交(读未提交),而导致了前后两次读取数据不一致的情况,这种事务并发的问题,我们把叫做脏读
    如果在转账的案例里面,我们第一个事务基于读取到的第二个事务未提交的余额进行了操作,但是第二个事务进行了回滚,这个时候就会导致数据库不一致。一个事务读取到了其他事务已提交的数据导致前后两次读取数据不一致的情况(修改和删除),叫做不可重复读。
    一个事务前后两次读取数据数据不一致,是由于其他事务插入数据造(insert)成的,这种情况我们把它叫做幻读

    如何实现事务一致性原则:

    第一种,既然要保证前后两次读取数据一致,那么我读取数据的时候,锁定我要操作的数据,不允许其他的事务修改就行了。这种方案我们叫做基于锁的并发控制 LockBased Concurrency Control(LBCC)。如果仅仅是基于锁来实现事务隔离,一个事务读取的时候不允许其他时候修改,那就意味着不支持并发的读写操作,会极大地影响操作数据的效率。
    另一种解决方案,如果要让一个事务前后两次读取的数据保持一致,那么我们可以在更新数据的时候建立一个备份或者叫快照,后面再来读取这个快照就行了。这种方案我们叫做多版本的并发控制 Multi Version Concurrency(MVCC)
    在 InnoDB 里面,这两种方案协同使用才能实现事务隔离级别。
    MVCC 也是通过 Undo log 实现的。
    MVCC:只能查找创建时间小于等于当前事务ID的数据和删除时间大于当前事务ID的行(或未删除)。在当前事务之后创建的数据,或者删除数据,都不会影响当前事务的查询操作。
     
     

     MyISAM和InnoDB分别支持什么粒度的锁

    MyISAM:支持表锁

    InnoDB:支持行锁和表锁

    共享锁:多个事务对于同一数据可以共享一把锁,都能访问到数据,但只读,不能修改。

    排他锁:写锁,X锁,排他锁不能与其他锁并存,若一个事务获取了一个数据行的排他锁,其他事务不能在获取该行的锁。

    存储引擎自己维护的,用户无法手动操作意向锁。

    意向共享锁(IS锁):事务准备给数据强行加入共享锁,说明一个数据行加共享锁前必须先取得该表的IS锁

    意向排他锁(IX锁):事务准备给数据行加入排他锁,说明事务在一个数据行加排他锁前必须要先取得该表的IX锁

    为什么要(表级别的)意向锁

    一个事务要成功地锁定一张表,前提:没有其他任何事务已经锁定了这张表的任意一行数据  此时如果没有一个意向锁的话,此时需要进行全表扫描。
    当有意向锁之后,我们只需要查看表上有没有加锁就行,类似于卫生间的们。会大大加快我们的查询效率。

    锁的作用:

      解决事务对数据并发访问的问题。锁的不是这一行数据,锁的是InnoDB中的索引。一张表有没有可能没有索引?不可能的。如果 一张表没有聚集索引,数据库就会自动创建一个默认的聚集索引,那么我们加锁的时候,由于是全表扫描,那么就会把每一行的隐藏的索引锁住,才会造成一个锁表的现象。

    锁的算法:

      这些数据库里面存在的主键值,我们把它叫做 Record,记录,那么这里我们就有 4 个 Record。根据主键,这些存在的 Record 隔开的数据不存在的区间,我们把它叫做 Gap,间隙,它是一个左开右开的区间。假设我们有 N 个 Record,那么所有的数据会被划分成多少个 Gap 区间?答案是 N+1,就像我们把一条绳子砍 N 刀,它最后肯定是变成 N+1 段。最后一个,间隙(Gap)连同它左边的记录(Record),我们把它叫做临键的区间,它是一个左开右闭的区间。

    如果主键索引不是整型,是字符怎么办呢?字符可以排序吗? 基于 ASCII 码

    记录锁

    第一种情况,当我们对于唯一性的索引(包括唯一索引和主键索引)使用等值查询,精准匹配到一条记录的时候,这个时候使用的就是记录锁。
    比如 where id= 1 4 7 10

    间隙锁

    第二种情况,当我们查询的记录不存在,无论是用等值查询还是范围查询的时候,它使用的都是间隙锁。
    举个例子,where id >4 and id <7,where id=6。  Gap 锁只在 RR 事务隔离级别里面存在。

    临键锁

    第三种情况,当我们使用了范围查询,不仅仅命中了 Record 记录,还包含了 Gap 间隙,在这种情况下我们使用的就是临键锁,它是 MySQL 里面默认的行锁算法,相当于记录锁加上间隙锁
    比如我们使用>5 <9 , 它包含了不存在的区间,也包含了一个 Record 7。锁住最后一个 key 的下一个左开右闭的区间。
    select  *  from t2 where id >5 and id <=7 for update; 锁住(4,7]和(7,10]
    select  *  from t2 where id >8 and id <=10 for update; 锁住 (7,10],(10,+∞)
     
    为什么要锁住下一个左开右闭的区间?—— 就是为了解决幻读的问题
      
      InnoDB中的间隙锁就是为了解决幻读。
  • 相关阅读:
    键盘弹出后上提view隐藏后下拉view还原并修改scroll过程中旋转屏幕到竖屏view显示错误
    iOS UI Element Usage
    ios notification
    retain和copy还有assign的区别
    UVA-11728 Alternate Task
    UVA-11490 Just Another Problem
    UVA-10127 Ones (数论)
    UVA-10710 Skyscraper Floors (找规律+幂取模)
    UVA-10539 Almost Prime Numbers
    UVA-10692 Huge Mods
  • 原文地址:https://www.cnblogs.com/guanyuehao0107/p/11973442.html
Copyright © 2020-2023  润新知