zoukankan      html  css  js  c++  java
  • 事务

    事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。

    数据库默认事务是自动提交的,也就是发一条sql它就执行一条。如果想多条SQL语句放在一个事务中执行,则需要对数据库自动提交的默认事务进行更改。

    JDBC中事务的使用:

    当Jdbc程序向数据库获得一个Connection对象时,默认情况下这个Connection对象会自动向数据库提交在它上面发送的SQL语句。每条单独的语句都是一个事务。每个语句后都隐含一个commit (默认)。

    一个独立SQL操作什么时候算执行完毕,JDBC规范是这样规定的:
    对数据操作语言(DML,如insert,update,delete)和数据定义语言(如create,drop),语句一执行完就视为执行完毕。
    对select语句,当与它关联的ResultSet对象关闭时,视为执行完毕。

    对存储过程或其他返回多个结果的语句,当与它关联的所有ResultSet对象全部关闭,所有update count(update,delete等语句操作影响的行数)和output parameter(存储过程的输出参数)都已经获取之后,视为执行完毕。

    若想关闭这种默认提交方式,让多条SQL在一个事务中执行,可使用下列语句:

    Connection.setAutoCommit(false);但是在之后还要把事务的提交方式改回到自动提交

    实例:

     1 publicvoid startTransaction(){
     2 
     3           
     4 
     5               con = DBCManager.getConnect();//获取连接对象
     6 
     7              
     8 
     9              
    10 
    11                             try {
    12 
    13                   //设置事务的提交方式为非自动提交:
    14 
    15               con.setAutoCommit(false);
    16 
    17               //将需要添加事务的代码一同放入try,catch块中
    18 
    19  
    20 
    21                   //创建执行语句
    22 
    23                   String sql ="delete from me where id = 7";
    24 
    25                   String sql1 = "update me set name ='chengong' ,age ='34' where id =4";
    26 
    27                   //分别执行事务
    28 
    29                   ps = con.prepareStatement(sql);
    30 
    31                   ps.executeUpdate();
    32 
    33                   ps = con.prepareStatement(sql1);
    34 
    35                   ps.executeUpdate();
    36 
    37                   
    38 
    39                   //在try块内添加事务的提交操作,表示操作无异常,提交事务。
    40 
    41  
    42 
    43                   con.commit();
    44 
    45                  
    46 
    47               } catch (SQLException e) {
    48 
    49               try {
    50 
    51                   //.在catch块内添加回滚事务,表示操作出现异常,撤销事务:
    52 
    53                   con.rollback();
    54 
    55               } catch (SQLException e1) {
    56 
    57                   // TODO Auto-generatedcatch block
    58 
    59                   e1.printStackTrace();
    60 
    61               }
    62 
    63                   e.printStackTrace();
    64 
    65               }finally{
    66 
    67                   try {
    68 
    69                      //设置事务提交方式为自动提交:
    70 
    71                      con.setAutoCommit(true);
    72 
    73                   } catch (SQLException e) {
    74 
    75                      // TODO Auto-generatedcatch block
    76 
    77                      e.printStackTrace();
    78 
    79                   }
    80 
    81                   DBCManager.release(rs, ps, con);
    82 
    83               }             
    84 
    85        }
    86 
    87  
    88 
    89  
    View Code

    (1)原子性(Atomicity)
    原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。

    (2) 一致性(consistency):事务在完成时,必须是所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。

    (3)隔离性(Isolation)
    事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。

    (4)持久性(Durability)
    持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响

    多个线程开启各自事务操作数据库中数据时,数据库系统要负责隔离操作,以保证各个线程在获取数据时的准确性。

    如果不考虑隔离性,事务并发处理可能会引起问题:

    脏读(dirty reads) 

    一个事务读取了另一个未提交的并行事务写的数据。 

    不可重复读(non-repeatable read)

    一个事务的操作导致另一个事务前后两次读取到不同的数据

    幻读(phantom read)

    一个事务的操作导致另一个事务前后两次查询的结果数据量不同。

    举例:
    事务A、B并发执行时,
    当A事务update后,B事务select读取到A尚未提交的数据,此时A事务rollback,则B读到的数据是无效的"脏"数据。
    当B事务select读取数据后,A事务update操作更改B事务select到的数据,此时B事务再次读去该数据,发现前后两次的数据不一样。
    当B事务select读取数据后,A事务insert或delete了一条满足A事务的select条件的记录,此时B事务再次select,发现查询到前次不存在的记录("幻影"),或者前次的某个记录不见了。

    JDBC定义了五种事务隔离级别:
    TRANSACTION_NONE JDBC驱动不支持事务
    TRANSACTION_READ_UNCOMMITTED 允许脏读、不可重复读和幻读。
    TRANSACTION_READ_COMMITTED 禁止脏读,但允许不可重复读和幻读。
    TRANSACTION_REPEATABLE_READ 禁止脏读和不可重复读,单运行幻读。
    TRANSACTION_SERIALIZABLE 禁止脏读、不可重复读和幻读。

    通常来说,一般的应用都会选择Repeatable read或Read committed作为数据库隔离级别来使用。

    mysql默认的数据库隔离级别为:REPEATABLE-READ

    如何查询当前数据库的隔离级别?select @@tx_isolation;

    如何查询当前数据库的隔离级别?select @@tx_isolation;

    如何设置当前数据库的隔离级别?set [global/session] transaction isolation level ...;

    ~此种方式设置的隔离级别只对当前连接起作用。

    set transaction isolation level read uncommitted;

    set session transaction isolation level read uncommitted;

    ~此种方式设置的隔离级别是设置数据库默认的隔离级别

    set global transaction isolation level read uncommitted;

    共享锁:共享锁和共享锁可以共存。共享锁和排他锁不能共存。在Serializable隔离级别下一个事务进行查询操作将会加上共享锁。

    排他锁:排他锁和所有锁都不能共存。无论什么隔离级别执行增删改操作时,会加上排他锁

    悲观锁:悲观的认为大部分情况下进行操作都会出现更新丢失问题。

    在每次进行查询的时候,都手动加上一个排他锁

                select * from table lock in share mode(读锁、共享锁)

                select * from table for update (写锁、排它锁)

    乐观锁:乐观的认为大部分的情况下都不会有更新丢失问题。通过时间戳字段,

    在表中设计一个版本字段version,当每次对数据库中的数据进行修改操作时,版本号都要进行增加。

    如果我的程序修改比较少查询比较多:乐观锁

    如果我的程序查询比较少修改比较多:悲观锁

    保存点(SavePoint)
    JDBC定义了SavePoint接口,提供在一个更细粒度的事务控制机制。当设置了一个保存点后,可以rollback到该保存点处的状态,而不是rollback整个事务。
    Connection接口的setSavepoint和releaseSavepoint方法可以设置和释放保存点。

  • 相关阅读:
    java面试之String源码中equals具体实现
    JVM虚拟机—JVM的垃圾回收机制(转载)
    Mysql学习笔记—视图
    Mysql学习笔记—索引
    JVM虚拟机—JVM内存
    设计模式—装饰器模式
    设计模式—代理模式
    设计模式—适配器模式
    设计模式—观察者模式
    设计模式—建造者模式
  • 原文地址:https://www.cnblogs.com/dobestself-994395/p/4270743.html
Copyright © 2011-2022 走看看