数据库相关(4) 事务处理

来源:互联网 发布:英语发音自测软件 编辑:程序博客网 时间:2024/05/16 05:08

1关于事务

         类似于多线程里的原子操作,不可分

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

starttransaction  开启事务

Rollback        回滚事务

Commit        提交事务


A向B借钱

A少了200,B加了200,倘若之前开启了事务,那么不提交的话,虽然查询的时候显示数据变了,可以回滚到之前的状态







在IDE里写代码,比如在两个语句中间出了一个bug,第一条语句执行了而第二条没执行咋搞



发现数据有问题

所以应该设置事务,让所有代码当做一个事务,参数设为false,表示一个整体

当出现异常的时候,要回滚,所以将回滚放到异常处理里

public class MyTransactionDemo {  public static  void main(String[] arg){  //1  加载驱动Connection conn=null;Statement st=null;ResultSet rs=null;try {DriverManager.registerDriver(new com.mysql.jdbc.Driver());//2.建立连接  conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb7","root","password");//3,获取statement 用于执行sql语句  st = conn.createStatement();//4,生成sql语句,并执行//executeconn.setAutoCommit(false);  String sql1 = "update account set money=money-200 where id =1;";boolean flag1 = st.execute(sql1);int b = 2/0;String sql2 = "update account set money=money+200 where id =2;";boolean flag2 = st.execute(sql2);conn.commit();} catch (SQLException e) {// TODO Auto-generated catch blocktry {conn.rollback();} catch (SQLException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}    e.printStackTrace();}finally{//6.关闭连接if (rs!=null) {try {rs.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(st!=null){try {st.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}if(conn!=null){try {conn.close();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}  }}

事务的特性

        原子性:要么都发生,要么都不发生

       一致性:继承于原子性,状态要一样,都发生改变,都进入改变后的状态,不能是一个改变了进入一个状态另一个发生了却没进入相应的状态。

借钱的例子,A从B那借100,A发生了改变B也发生了改变,这叫原子性。A借来100变成了1100,而B则相应的减少了100变成900,不能是B虽然发生借出100这个事件最后却不是900这种情况,这叫一致性。

       持久性:发生了改变,提交后就是永久的,即使数据库出了故障也不应该影响这次改变。其实是数据的改变会写到硬盘上,出现问题也不会回到改变前。

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

 

隔离的级别

 

脏读一个事务读取了另外一个事务未提交的数据

        比如A转账给B100元,A减100,但是未提交;B已经能看到自己多了100,这就是脏读。会出的问题是A可以回滚,此时B就会发现自己的数据不一致,放在转账这个事例里就相当于B少了100.

        Transaction 1 修改了一行数据,然后 Transaction 2 在Transaction 1 还未提交修改操作之前读取了被修改的行。如果 Transaction 1 回滚了修改操作,那么 Transaction 2 读取的数据就可以看作是从未存在过的

 

不可重复读在一个事务内读取表中的某一行数据,多次读取结果不同。

       读的时候 别的事务修改了数据  update

       A的账户,刚刚银行查到是200,此时A又存入100,银行发现变成300,若没有其他说明A的操作,对于银行来说,这个数据就出现了混乱。

       比如银行程序需要将查询结果分别输出到电脑屏幕和写到文件中,结果在一个事务中针对输出的目的地,进行的两次查询不一致,导致文件和屏幕中的结果不一致,银行工作人员就不知道以哪个为准了

        Transaction 1 读取一行数据,然后 Transaction 2 修改该行并提交修改操作。当 Transaction 1 试图重新读取该行时,它就会得到不同的数据值(如果该行被更新

 

虚读在一个事务内读取到了别的事务插入的数据,导致前后读取不一致。

         读的时候 别的事务插入或者删除了数据   insert  delete 

         Transaction 1 读取满足某种搜索条件的一些行,然后 Transaction 2 插入了符合 Transaction 1 的搜索条件的一个新行。如果 Transaction 1 重新执行产生原来那些行的查询,就会得到不同的行

 

数据库共定义了四种隔离级别 从高到低 mysql默认是Repeatable read,并且Serializable这里似乎有点问题,和默认的效果看起来一样。

        Serializable:可避免脏读、不可重复读、虚读情况的发生。(串行化)

        Repeatable read:可避免脏读、不可重复读情况的发生。

        Read committed:可避免脏读情况发生。

        Read uncommitted:最低级别,以上情况均无法保证。(读未提交)。


0 0
原创粉丝点击