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

        数据库的事务特性及事务的隔离级别:

  数据库的事务一般支持一下的四个特性:原子性,一致性,隔离性,永久性.简称(ACID)。

⑴ 原子性(Atomicity):

  原子性是指事务包含的所有操作要么全部成功,要么全部失败回滚。

⑵ 一致性(Consistency):

  一致性是指事务必须使数据库从一个一致性状态变换到另一个一致性状态,也就是说一个事务执行之前和执行之后都必须处于一致性状态。

  拿转账来说,假设用户A和用户B两者的钱加起来一共是5000,那么不管A和B之间如何转账,转几次账,事务结束后两个用户的钱相加起来应该还得是5000,这就是事务的一致性。

⑶ 隔离性(Isolation):

  隔离性是当多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务的操作所干扰,多个并发事务之间要相互隔离。

  即要达到这么一种效果:对于任意两个并发的事务T1和T2,在事务T1看来,T2要么在T1开始之前就已经结束,要么在T1结束之后才开始,这样每个事务都感觉不到有其他事务在并发地执行。

⑷ 持久性(Durability):

     持久性是指一个事务一旦被提交了,那么对数据库中的数据的改变就是永久性的,即便是在数据库系统遇到故障的情况下也不会丢失提交事务的操作。

下面我们来看看事务隔离机制:

    当多个线程都开启事务操作数据库时,数据库系统要进行隔离操作,以保证各个线程获取数据的准确性,如何不考虑事务的隔离性,会发生的事务的相应的问题。

  1.脏读(dirty reads):

    一个事务处理过程中,读到另一个未提交事务的数据。另一个事务出现异常等原因,发生回滚(rollback),导致数据不一致。

   eg:

      当一个事务正在多次修改某个数据,而在这个事务中这多次的修改都还未提交,这时一个并发的事务来访问该数据,就会造成两个事务得到的数据不一致。例如:用户A向用户B转账100元,对应SQL命令如下

     update account set money=money+100 where name=’B’;  (此时A通知B)

     update account set money=money - 100 where name=’A’;

  当只执行第一条SQL时,A通知B查看账户,B发现确实钱已到账(此时即发生了脏读),而之后无论第二条SQL是否执行,只要该事务不提交,则所有操作都将回滚,那么当B以后再次查看账户时就会发现钱其实并没有转。在实际应用中脏读是绝对不允许的。

 2.不可重复读(non-repeatable reads)

不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了.不可重复读针对于原有的值,比如如

 select name,empno tbl_user where id=1; 原来是name 值 刘德华,现在变成了 张学友。重点在于前后两次的值不一样,用于数据的修改。

 3.虚读(幻读 phantom reads)

 一个事务范围内多次查询却返回了不同的数据数量。相同的sql条件查询得出不同的结果:

select name empno tbl_user where age >12; 原来满足条件的只有12条记录,现在出现了15条记录。在第一次查询的间隔其他事务插入了3条数据。幻读针对于新增和删除,针对数量变化。这也是幻读和可重复读的区别。

  这里在总结下:不可重复读和虚读的区别:

 如果使用锁机制来实现这两种隔离级别,在可重复读中,该sql第一次读取到数据后,就将这些数据加锁,其它事务无法修改这些数据,就可以实现可重复 读了。但这种方法却无法锁住insert的数据,所以当事务A先前读取了数据,或者修改了全部数据,事务B还是可以insert数据提交,这时事务A就会 发现莫名其妙多了一条之前没有的数据,这就是幻读,不能通过行锁来避免。需要Serializable隔离级别 ,读用读锁,写用写锁,读锁和写锁互斥,这么做可以有效的避免幻读、不可重复读、脏读等问题,但会极大的降低数据库的并发能力。

数据库的隔离级别

1. 读未提交(READ_UNCOMMITTED)

         A constant indicating that dirty reads, non-repeatable reads and phantom reads

  can occur. This level allows a row changed by one transaction to be read by

  another transaction before any changes in that row have been committed

  (a "dirty read"). If any of the changes are rolled back, the second

  ransaction will have retrieved an invalid row.

    最低级别,任何情况都无法保证。

 2.读已提交(READ_COMMITTED)

         * A constant indicating that dirty reads are prevented; non-repeatable reads

* and phantom reads can occur. This level only prohibits a transaction

* from reading a row with uncommitted changes in it.

   可避免脏读的发生。

3.可重复读(REPEATABLE_READ)

         * A constant indicating that dirty reads and non-repeatable reads are

* prevented; phantom reads can occur. This level prohibits a transaction

* from reading a row with uncommitted changes in it, and it also prohibits

* the situation where one transaction reads a row, a second transaction

* alters the row, and the first transaction rereads the row, getting

* different values the second time (a "non-repeatable read").

 可避免脏读、不可重复读的发生。

4.串行化(Serializable)

         * A constant indicating that dirty reads, non-repeatable reads and phantom

* reads are prevented. This level includes the prohibitions in

* {@code ISOLATION_REPEATABLE_READ} and further prohibits the situation

* where one transaction reads all rows that satisfy a {@code WHERE}

* condition, a second transaction inserts a row that satisfies that

* {@code WHERE} condition, and the first transaction rereads for the

* same condition, retrieving the additional "phantom" row in the second read.

   可避免脏读、不可重复读、幻读的发生。

在实际运用中:设置数据库的隔离级别一定要是在开启事务之前! 

 如果是使用JDBC对数据库的事务设置隔离级别的话,也应该是在调用Connection对象的setAutoCommit(false)方法之前。调用Connection对象的setTransactionIsolation(level)即可设置当前链接的隔离级别,至于参数level,可以使用Connection对象的字段:

int TRANSACTION_NONE = 0; 没有设置隔离级别

int TRANSACTION_READ_UNCOMMITTED = 1;读未提交

int TRANSACTION_READ_COMMITTED = 2; 读已提交

int TRANSACTION_REPEATABLE_READ = 4;可重复读

int TRANSACTION_SERIALIZABLE = 8;串行化

后记:隔离级别的设置只对当前链接有效。对于使用MySQL命令窗口而言,一个窗口就相当于一个链接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对该Connection对象有效,与其他链接Connection对象无关。

 

猜你喜欢

转载自www.cnblogs.com/caibixiang123/p/9224866.html