zoukankan      html  css  js  c++  java
  • 事务、事务操作、事务隔离级别

    1、什么是事务:

      事务是逻辑上的一组操作,要么都执行,要么都不执行

      例如:银行转账,A转账1000元给B,这个转账就涉及到两个操作:将A余额减去1000元,将B余额加上1000元。但是外一在转账的过程中银行的系统奔溃,导致A只减了,B没有加,这样就出错了。事务就是要保证这两个操作,要么都成功,要么都失败。

    2、事物的特性:

      事务必须同时满足以下4个特性。

    (1)原子性:原子性是指一个事务必须被视为一个不可分割的最小工作单元,只有事务中所有的数据库操作都执行成功,才算整个事务执行成功,事务中如果有任何一个SQL语句执行失败,已经执行成功的SQL语句也必须撤销,数据库的状态退回到执行事务前得状态。

    (2)一致性: 在一个事务执行之前和执行之后数据库都必须处于一致性状态。假如数据库的状态满足所有的完整性约束,就说该数据库是一致的。

       一致性是指事务将数据库从一种状态转变为下一种一致的状态。例如,在表中有一个字段为姓名,具有唯一约束,即姓名不能重复,如果一个事务对姓名进行了修改,使得姓名不唯一了,这就是破坏了事务的一致性要求,如果事务中某个事务失败了,系统可以自动撤销事务,返回初始化的状态。

    (3)隔离性:并发访问数据库时,一个用户的事务不被其他事务所干扰,各并发事务之间数据库是独立的;

      隔离性还可以称为并发控制、可串行化、锁等,当多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。

    (4)持久性:一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障也不应该对其有任何影响。

    3、事务的操作:

    (1)commit 提交:

    start transaction;
    update account set money=money+100 where name=‘a’;
    update account set money=money-100 where name=‘b’;

      这时只是开启了事务,语句进行了执行,此时用 select 语句查询表中的数据,发生了改变,a 变成了1100,b 变成了900。若这时我们断开数据库连接,重新登录,再次select查询表,发现ab这两个值又重新变回了了1000,1000。这是由于我们的事务实际上只是执行了,并没有提交,还没有提交就退出数据库了,由于事务语句不能自动提交,因此当前的操作就被自动取消了。需要手动使用commit进行提交。

    start transaction;
    update account set money=money+100 where name=‘a’;
    update account set money=money-100 where name=‘b’;
    commit

    (2)rollback 回滚:

      事务执行完之后,我们没有退出数据库连接,但此时想要将事务操作取消,可以使用事务的回滚操作。

    RollBack;

    4、并发事务带来的问题:

      在典型的应用程序中,多个事务并发运行,操作相同的数据来完成各自的任务,即:多个用户对同一数据进行操作。可能会导致以下问题:

    (1)脏读(Dirty read):一个事务访问数据库对数据进行修改,但是没有提交,这时另一个事务也访问了这个数据,并使用这个数据。因为第一个事务没有提交,因此第二个事务读取的其实是脏数据,并且根据脏数据做的所有的操作都是错误的。

      一个事务读到了其他事务未提交的数据。

    (2)丢失修改(Lost to modify):两个事务几乎同时读取了同一个数据,事务1修改了该数据后,事务2也修改了该数据。两个事务提交后,事务1的结果被事务2的结果覆盖掉了,即事务1的修改丢失了,因此称为丢失修改。例如:事务1读取某表的数据为A=20,事务2读取某表的数据也为A=20,事务1修改A=A-1,事务2修改A=A-2,最终的结果就是A=18,事务1的修改丢失了。

    (3)不可重复读(Unrepeatableread):事务1要多次读取某一个数据,在事务1还没结束时,另一个事务也访问该数据,并修改该数据。那么,在事务1两次读取数据之间,由于事务2的修改,导致事务1两次读取该事物的结果不一样。这种,在一个事务多次读取同一数据,发生了不一样的情况称为不可重复读。

      一个事务在两次读取的过程中,有其他的事务对数据进行了修改,导致两次读取结果不一样。

    (4)幻读(Phantom read):事务1读取了几行数据,事务2插入了几条数据,当事务1再次查询的时候,发现多出了几条原本不存在的记录,就好像发生了幻觉,所以称为幻读。

      一个事务两次读取的过程中,有其他的事务对数据进行新增,导致两次读取的条数不一样。

    不可重复读、幻读的区别:

      不可重复读的重点是修改,幻读的重点在于新增或者删除。
      例1(同样的条件, 你读取过的数据, 再次读取出来发现值不一样了 ):事务1中的A先生读取自己的工资为 1000的操作还没完成,事务2中的B先生就修改了A的工资为2000,导 致A再读自己的工资时工资变为 2000;这就是不可重复读。
      例2(同样的条件, 第1次和第2次读出来的记录数不一样 ):假某工资单表中工资大于3000的有4人,事务1读取了所有工资大于3000的人,共查到4条记录,这时事务2 又插入了一条工资大于3000的记录,事务1再次读取时查到的记录就变为了5条,这样就导致了幻读。

    5、事务的隔离级别:*****

    (1)读取未提交(READ-UNCOMMITTED):允许读取尚未提交的数据变更。隔离级别最低,可能产生脏读、幻读、不可重复读;

    (2)读已提交(READ-COMMITTED):允许读取并发事务已提交的数据,没提交的数据不能读。能够阻止脏读,但是会产生幻读、不可重复读;

    (3)可重复读(REPEATABLE-READ):对同一数据的多次读取结果是一致的。除非是自身事务对其进行修改,能够阻止脏读、不可重复读,但会产生幻读。

    (4)可串行化(SERIALIZABLE):最高的隔离级别,完全服从ACID的隔离级别。所有事务逐个执行,事务之前完全不产生干扰,能够阻止所有的并发问题。

    补充:MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。

      InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。因为隔离级别越低,事务请求的锁越少,所以大部分数据库系统的隔离级别都是READ-COMMITTED(读取提交内容):,但是你要知道的是InnoDB 存储引擎默认使用 REPEATABLE-READ(可重读)并不会有任何性能损失。InnoDB 存储引擎在 分布式事务 的情况下一般会用到SERIALIZABLE(可串行化)隔离级别。






  • 相关阅读:
    python笔记-13 mysql与sqlalchemy
    python笔记-12 redis缓存
    python笔记-11 rabbitmq
    python笔记-10(socket提升、paramiko、线程、进程、协程、同步IO、异步IO)
    python笔记-9(subprocess模块、面向对象、socket入门)
    python笔记-7(shutil/json/pickle/shelve/xml/configparser/hashlib模块)
    leetcode98
    leetcode543
    leetcode85
    leetcode84
  • 原文地址:https://www.cnblogs.com/guoyu1/p/12234664.html
Copyright © 2011-2022 走看看