zoukankan      html  css  js  c++  java
  • mysql事务详解

    事务的四大特性ACID如下:

          原子性:事务中的所有操作,要么全部完成,要么不做任何操作,不能只做部分操作。如果在执行的过程中发了错误,要回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过。

     

     

     

     

    事务的四大隔离级别如下:

    一、读未提交。(A事务能够读取到B事务对数据的增删改操作)

      该事务级别会出现脏读问题。

     

    二、读已提交。(该事务级别不会出现脏读问题)

       只要一个事务A提交了,那么事务A中对数据库表的增删改操作,都会直接反映到事务B上,因此事务B中可以查看到最新的数据。

    三、可重复读。(解决了不可重复读,即其他事务的提交,在该事务中看不见,也就是select时,别的事务提交不会影响select语句的结果,但是因为别的事务已经提交了,所以在数据库中是真实存在的,只是在该事务中给屏蔽了一眼,相当于障眼法,如果此时针对别的事物的插入的数据做修改删除操作,那么会起到实际作用的,但是如果新增一条和别的事务插入的记录有违反唯一约束的,那么新增会失败。如果其他事务更新了数据,那么在本事务中不可见,)

    测试如下:

           1、

           (1)开启两个会话A和B,并设置两个会话的数据库隔离级别为可重复读。

     

     

         (2)在两个会话中分别开启两个事务A和事务B,然后分别查询同一张表user,结果如下。

     

     

        (3)先在A事务中插入一条记录并提交,然后在B事务中查询。

    --------------------------------------------------------------------------------------------------------------

     综合上面的测试说明:

          (1)如果其他事务插入了数据,那么在该事务中分几种情况:

              如果直接查询,那么不会查询到其他事务提交的最新数据,即屏蔽了外界的变化,保持了数据在一个事务中任何地方查询看到的结果都是完全相同一致的;

              如果在该事务中插入与其他事务提交的数据产生违反唯一性约束的话,那么该事务中导致插入失败,因为在该事务中看不见其他事务的操作,即屏蔽了外界;

              但是如果更新数据时,如果更新数据的条件包含了其他事务中提交的插入数据,那么更新之后会看到这些其他事务中提交的插入数据,而且被更新了,如果更新条件不包含其他事务提交的数据,那么这些数据还是不会出现的。

             如果删除数据时,如果删除数据的条件包含了其他事务中提交的数据,那么删除之后会看到这些其他事务中提交的数据也被删除了,如果删除条件不包含其他事务提交的数据,那么这些数据还是不会出现,也不会被删除。

          (2)如果其他事务更新了数据,那么在该事务中分几种情况:。

     

              如果直接查询,那么不会显示其他事务提交的最新数据,即屏蔽了外界的变化,保持了数据在一个事务中任何地方查询看到的结果都是完全相同一致的;

              如果在该事务中插入与其他事务提交的删除数据有相同主键或唯一索引的话,那么该事务中插入会失败;

     

              但是如果更新数据时,如果更新数据的条件包含了其他事务中提交的数据,那么更新之后会看到这些其他事务中提交的更新数据,而且被更新了,如果更新条件不包含其他事务提交的数据,那么这些数据还是不会出现的。

     

             如果删除数据时,如果删除数据的条件包含了其他事务中提交的更新数据,那么删除之后会看到这些其他事务中提交的更新数据也被删除了,如果删除条件不包含其他事务提交的数据,那么这些更新数据还是不会出现,也不会被删除。

          (3)如果其他事务删除了数据,那么在该事务中分几种情况:。

              如果直接查询,那么仍然能够查询到其他事务提交的删除数据,即屏蔽了外界的变化,保持了数据在一个事务中任何地方查询看到的结果都是完全相同一致的;

              但是如果更新数据时,如果更新数据的条件包含了其他事务中提交的删除数据,那么会出现更新异常,如果更新条件不包含其他事务提交的数删除据,那么不会出现更新异常。

              如果删除数据时,如果删除数据的条件包含了其他事务中提交的删除数据,出现删除异常,如果删除条件不包含其他事务提交的删除数据,则不会出现删除异常。

          (4)如果其他事务提交了的最新数据,在该事务中第一次查询,将是最新的数据,对同一张表查询将会保持相同一致的。即在事务中,任何一张表第一次读取时,那么此时的数据就是最新的,之后如果再次读取时,则不会改变,除非上述情况。(首次读取=最新数据)。

     

     

     举例说明:执行时间如下顺序:

       (1)事务A开启,并执行第一次查询操作。

     

       (2)事务B更新数据并提交。

     

       (3)事务A更新B更新过的数据,结果发现不是104,而是140,这就是幻读。明明更新前一刻查询是4,再更新一次,结果却是用到了B事务提交过来的数据。

     

       (4)因此需要特别注意这类幻读造成的危害。后果很严重。那么如何避免这类严重问题?

          (a)添加读锁。select * from t1 where id=5 lock in share mode;如果在事务A中对指定的记录行添加读锁,那么其他事务最多也只能给这些记录行添加读锁,其他添加事务给这些记录添加不了写锁了,如果其他事务添加写锁,那么会被阻塞,直到其他所有读锁都释放了。因此在事务A结束之前,这些记录行一定不会被其他事务修改/删除/插入(注意:此处插入是指插入与这些记录行有相同的唯一索引或主键的数据),只有当这些记录行的其他读锁和写锁都释放了,那么才能够被修改/删除/插入相同。但是如果同时想在事务A中修改加了读锁的这些记录行时,只有当这些记录行还没有被其他事务加读锁,那么这些被自己加了读锁的记录行就可以修改;如果有其他事务也给这些记录行添加了读锁,那么修改操作将会被阻塞,直到其他事务的读锁都释放了才能被修改成功。因此,给指定记录行添加读锁,只是为了在本事务执行期间(事务还没有结束)不想让这些记录行的数据被修改/删除/插入相同,同时本事务也不想修改/删除/插入相同这些记录行。也就是冻结数据,不让任何事务篡改已经存在的数据。切记自己给这些记录行添加了读锁,同时自己又要更新/删除/插入相同这些记录行,这会带来严重的性能下降和不确定性增加,效率也会低下

          (b)添加写锁。select * from t1 where id=5 for update;如果事务A给指定的记录行添加了写锁,那么其他事务进行select读取这些记录行是一点都没有问题的。如果其他事务对这些记录行尝试添加读锁或者写锁时,都会被阻塞掉,等待时间到了之后而且事务A还没有结束时就会返回空的数据行,如果等待时间还没有到事务A却结束了,那么其他事务可以获取到指定的记录行的读锁或写锁。如果事务A还没有结束,那么其他事务只能读取到这些记录行,但是不能更新/删除/插入相同这些记录行,如果其他事务尝试更新/删除/插入相同这些记录行就会被阻塞,直到事务A结束或等待超时,如果事务A提前结束,那么更新/删除会成功,等待超时肯定是失败了。这些记录行的写锁,可以在本事务中来修改/删除这些记录行。因此,添加指定记录行的写锁,其他事务可以select简单查询,禁止了其他事务写锁读和读锁读,也禁止了其他事务更新/删除这些记录行,本事务却可以任意地更新/删除这些记录行 

       (5)简单可重复读现场举例。

          (a)先查询数据再开启事务A。

     

          (b)开启事务B,然后插入一条记录(6,6)并提交成功。

     

          (c)在事务A中第一次查询数据。获取到了最新的数据。

     

     

          (d)再开启另外一个事务C,并插入一条记录(7,7),并提交成功。

     

          (e)再在事务A中进行第二次简单select查询。结果和第一次查询的结果相同。

     

       (6)Innodb存储引擎的mvcc并发控制。

     

     

     

     

    四、可串行化。

    igoodful@qq.com
  • 相关阅读:
    二分查找算法
    java多线程模拟停车位问题
    ECShop模板原理
    linux 常用命令 自己 积累
    ubuntu忘记root密码解决
    centos下一键安装lamp环境,快捷,方便
    腾讯php部分面试题答案
    PHP面试题集
    php笔试题
    流行的php面试题及答案
  • 原文地址:https://www.cnblogs.com/igoodful/p/8988113.html
Copyright © 2011-2022 走看看