MySQL数据库事务的特性和隔离级别

在介绍数据库事务以及隔离级别时,我们先来了解关于事务的几个概念

关于事务的几个特性,简称ACID

A事务的原子性(Atomicity):对于一个事务要么全部执行,要么全部不执行,也就是说一个事务不可能执行一半就停止了。

C事务的一致性(Consistency):事务的运行并不改变数据库的一致性。

I事务的隔离性(Isolation):隔离性保证了并发执行多个事务和串行执行过个事务的效果是一样的。隔离性是并发控制的目标,通过并发控制,一个未完成的事务对其他事务是不可见的。

D事务的持久性(Durability):持久性保证了一个事务的状态提交后,就不会发生改变,

脏读

     脏读就是当一个事务A正在读取数据,另外一个事务B对数据库进行了修改,但是并没有commit, 事务A查询到的数据就是事务B未提交的数据。

    比如:张三的账户上有5000元,A事务将张三的工资改为3000元,并未提交,这个时候事务B来查询张三的工资,发现张三的工资是3000元。如果事务A在提交的时候发生了异常,发生回滚,恢复到修改前的状态,变为5000元,但是事务B读取到的是3000元,其实就是脏数据。

幻读

     幻读指的是事务不是独立执行时发生的一种现象。比如事务A对数据库中表中的数据进行了修改,这个修改涉及到数据库中的所有行,同时第二个事务也对数据库当中的表进行了修改,比如增加了一行,那么事务A会发现竟然还有一行没有修改,就好像发生了幻觉

     比如,事务A查询出来的表中有10条数据,事务B添加了一条数据,事务A再次读取数据,发现数据变成了11条,就好像发生了幻觉

不可重复读

     这个指的是,在一个事务内,多次读同一个数据。在一个事务还没结束之前,另外一个事务对数据进行了修改,导致一第一个事务两次读取到的数据是不同的,这样就发生了在同一个事务当中,两次读取数据不一致的问题,因此成为不可重复读。

   比如:张三在事务A当中读取到工资为5000,事务A还没有结束,这个时候事务B将张三的工资改成了3000,这个时候事务A再去读张三的工资时候,发现工资变成了3000,同一个事务当中,两次读取到的数据不一致。

了解以上内容之后,我们来看下数据库事务隔离的级别

未交的读-Read Uncommited

  account表当中仅包含字段id,account

    用户A设置事务级别为 

set session transaction isolation level read uncommitted;
start transaction;
select * from account;

     用户B也是未提交的读

set session transaction isolation level read uncommitted;
start transaction;
update account set account=account+200 where id = 1;

这个时候用户A执行查询,查询到的数据是用户B修改过并未提交的数据。

未提交的读就会造成我们上面说的脏读,这个事务级别是最低的。

已提交的读-Read Commited(大多数数据库的默认级别)

     继续上面的例子,在用户A当中我们执行

update account set account=account-200 where id=1;

   在用户B当中,将用户B的事务级别设置成read commited,然后查询账户余额,并没有发生改变

  当用户A 执行commit之后,用户B再进行查询,发现数据被修改

   在这个事务下,会发生的问题就是不可重复读,比如事务B在事物A未执行操作之前读取到的数据,和事务A提交之后查到的数据是不一致的。当然也有可能会发生幻读

可重复读-Repeatable(MySQL默认级别)

    接着上面的例子,我们在用户B当中把事务级别设置成可重复读

set session transaction isolation level repeatable read;
start transaction;

    紧接着在用户A当中插入一条数据,并提交

insert into account(id,account) value(3,1000);
commit;

  这个时候,数据库当中已经保存了id=3这条记录  

 回到用户B所在会话,发现并没有id=3这条记录, 当我们尝试插入id=3数据时,会提示id=3已经存在,不能重复插入。

 这种事务下,当前会话是可以重复读的,并且每次读到的数据都是一致的,不管其他事务有没有提交。

串行化-Serializable

   设置用户B为Serializable,用户B下执行查询操作

set session transaction isolation level serializable;
start transaction;
select * from account;

用户A插入一条数据id=3,这个时候我们会发现用户A会陷入等待中,如果超时,就会提示Lock wait time out

只有在等待期间,我们将用户B的会话事务提交,那么用户A才可以插入成功。

  这种事务级别明显是最严格的,能保证数据不会出问题,但是如果数据量很大的情况下,性能肯定是会有所影响的。

参考:数据库

          五分钟搞清楚MySQL事务隔离级别

猜你喜欢

转载自blog.csdn.net/summerzbh123/article/details/81189752