一、事务是什么?
事务,通俗点说,就是为完成一个业务功能而执行的多条指令的集合。比如在java程序的业务层的一个方法,这个方法干了两件事A和B,那从调用这个方法开始,到这个方法结束,就是一个事务。另外,比如在oracle当中,默认是手动提交事务,那么在执行多条sql(或者一条)语句后,去提交当前事务,也是完成了一个事务。
二、事务的四个特性
事务有四个基本特性,分别是:
原子性(atomicity):一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
三、并发访问下事务产生的问题
并发访问下事务会产生一些问题,之所以会产生这些问题,主要是因为多个线程在对相同的一条或多条数据进行增删改查的操作,如果所有的线程都在同一时间对相同的数据进行查询的话,那除了大并发或大数据量下会出现访问效率低的情况,其他是不会有什么问题的。那在多个线程并发操作数据库具体会出现的问题,总结为一下三点:
1、脏读:事务A读到了事务B还没有提交的数据。就是说一个线程对于数据库的修改还未提交,但是被其他的线程给读到了;
2、不可重复读:在一个事务里面读到了两次某条或多条数据,读出的数据不一致。大概意思是一个事务里面会去查询两次相同的数据,但是查出来的数据会不一致,这自然是由于其他线程对这些数据进行了操作;
3、幻读:指的是在一个事务的操作中发现了未操作的数据。幻读与不可重复读一样都是在同一个事务里两次操作发现数据库查询的结果不一致,他们的区别简单来说是不可重复读的出现可能是因为update造成的,而幻读是因为其他线程有进行insert的操作。比如在线程A里面讲user表的status全部修改为1,但是线程B又插入了一条status=2的数据,那这个时候线程A再进行查询,就会出现幻读。
四、针对并发访问而存在的事务隔离级别
针对并发访问而存在的问题,有相应的事务隔离级别去解决这些问题。当然,事务隔离级别设置得越高,在程序的性能上也会有相应的影响,所以在进行程序设计的时候,经常要在效率与安全之间有一个衡量,以做取舍。
在Spring里面配置事务会有五中隔离级别,分别是:
1.DEFAULT,这里是指默认去使用当前数据源中的事务隔离级别;
2.READ_UNCOMMITTED,翻译过来是读未提交,既然可以读其他事务未提交的数据,那肯定是脏读、不可重复读、幻读的情况都会出现;
3.READ_COMMITED,读已提交,允许读已提交的数据,这种事务隔离级别不会出现脏读,但是可能会出现不可重复读与幻读;
4.REPEATABLE_READ,顾名思义,repeatable,这种事务级别可以防止脏读与不可重复读的出现,但是幻读的出现仍不能防止;
5.SEARIALIZABLE,这是事务隔离的最高级别,该事务级别可以防止脏读、不能重复读与幻读的出现,但是相应的,它的安全是建立在牺牲效率的基础之上的。
五、mysql默认的事务隔离级别
在mysql中可以以下sql语句去查询当前数据库设置的事务隔离级别。
SELECT @@tx_isolation;
当然,也可以通过相关的sql语句去修改当前数据库的事务隔离级别。
mysql本身默认的隔离级别为REPEATABLE_READ。