zoukankan      html  css  js  c++  java
  • 事务隔离机制_悲观锁_乐观锁

    5. 事务并发处理
      a) 事务的特性:ACID
        i.Atomicity 原子性
        ii.Consistency 一致性
        iii.Isolation 隔离性
        iiii.Durability 持久性
      b) 事务并发时可能出现的问题
        i. 第一类丢失更新(Lost Update)

    时间 取款事务A 存款事务B
    T1 开始事务  
    T2   开始事务
    T3 查询账户余额为1000元  
    T4   查询账户余额为1000元
    T5  

    汇入100元把余额改为1100元

    T6   提交事务
    T7 取出100元把余额改为900元  
    T8 撤销事务  
    T9

    余额恢复为1000元(丢失更新)

     

        ii.脏读(Dirty Read)

    时间 取款事务A 转账事务B
    T1 开始事务  
    T2   开始事务
    T3   查询账户余额为1000元
    T4   汇入100元把余额改为1100元
    T5

    查询账户余额为1100元(读取脏数据)

     
    T6   回滚
    T7 取款 1100  
    T8 提交事务失败  

        iii.不可重复读(non-repeatable read) 

          在一个事务中前后两次读取的结果并不致,导致了不可重复读,会导致不一致的分析。

    时间 取款事务A 转账事务B
    T1 开始事务  
    T2   开始事务
    T3 查询账户余额为1000元  
    T4   汇入100元把余额改为1100元
    T5   提交事务
    T6 查询账户余额为1100元  
    T7 提交事务  

        iiii.第二类丢失更新——不可重复读的特殊情况(second lost update problem)

    时间 转账事务A 取款事务B
    T1   开始事务
    T2 开始事务  
    T3   查询账户余额为1000元
    T4 查询账户余额为1000元  
    T5   取出100元把余额改为900元
    T6   提交事务
    T7 汇入100元  
    T8 提交事务  
    T9

    把余额改为1100元(丢失更新)

     

        v.幻读(phantom read)

    时间 查询学生事务A 插入新学生事务B
    T1 开始事务  
    T2   开始事务
    T3 查询学生为10人  
    T4   插入一个新学生
    T5 查询学生为11人  
    T6   提交事务
    T7 提交事务  

    c) 数据库的事务隔离机制
      i. 查看 java.sql.Connection 文档
      ii.
        (1:read-uncommitted
           2:read-committed
           4:repeatable read
           8:serializable)
      1. 只要数据库支持事务,就不可能出现第一类丢失更新
      2. read-uncommitted 会出现 dirty read,phantom-read,non-repeatable read 问题
      3. read-commited 不会出现 dirty read.因为只有一个事务提交才会读出结果,但仍然会出现 non-repeatable 和 phantom-read
      4. repeatable read


    d) 设定 hibernate 的事务隔离级别
      i. hibernate.cfg.xml 配置文件中进行配置:hiberante.connection.isolation=2
      ii.用悲观锁解决 repeatable read 的问题(依赖于数据库的锁)
        1.select ... for update
        2.load(xx.class,i,LockMode.Upgrade),

       a) LockMode.NONE 无锁的机制,Transaction 结束时,切换到此模式

         b) LockMode.READ 在查询的时候 hibernate 会自动获取锁

         c) LockMode.WRITE insert update hibernate 或自动获取锁

       d) 以上三种锁的模式,是 hibernate 内部使用的

         e) LockMode.UPGRADE_NOWAIT Oracle 支持的锁的方式

        如下:

     1     @Test
     2     public void testPessimisticLock(){
     3         Session session = sf.getCurrentSession();
     4         session.beginTransaction();
     5         
     6         Account a = (Account) session.load(Account.class, 1,LockMode.UPGRADE);//一般用 UPGRADE
     7         int balance = a.getBalance();
     8         //do some caculations
     9         balance -= 10;
    10         a.setBalance(balance);
    11         
    12         session.getTransaction().commit();
    13     }

     e) Hibernate(JPA)乐观锁定(ReadCommitted)

     1 package com.bjsxt.hibernate;
     2 
     3 import javax.persistence.Entity;
     4 import javax.persistence.GeneratedValue;
     5 import javax.persistence.Id;
     6 
     7 @Entity
     8 public class Account {
     9     
    10     private Integer id;
    11     
    12     private int balance;
    13 
    14     @Id
    15     @GeneratedValue
    16     public Integer getId() {
    17         return id;
    18     }
    19 
    20     public void setId(Integer id) {
    21         this.id = id;
    22     }
    23 
    24     public int getBalance() {
    25         return balance;
    26     }
    27 
    28     public void setBalance(int balance) {
    29         this.balance = balance;
    30     }
    31     
    32 }

      保存:

     1     @Test
     2     public void testOptimisticLock(){
     3         Session session = sf.openSession();
     4         Session session2 = sf.openSession();
     5         
     6         session.beginTransaction();
     7         Account a1 = (Account) session.load(Account.class, 2);
     8         
     9         session2.beginTransaction();
    10         Account a2 = (Account) session2.load(Account.class, 2);
    11         
    12         a1.setBalance(900);
    13         a2.setBalance(1100);
    14         
    15         session.getTransaction().commit();
    16         System.out.println(a1.getVersion());
    17         
    18         session2.getTransaction().commit();//第二次提交时会对比 version 字段,如果值改变,则事务处理失败,回滚
    19         System.out.println(a2.getVersion());
    20         
    21         session.close();
    22         session2.close();
    23     }

    jar包链接: https://pan.baidu.com/s/1qYHdnbA 密码: p429

    悲观锁代码链接: https://pan.baidu.com/s/1o8Llad0 密码: 1x2x

    乐观锁代码链接: https://pan.baidu.com/s/1c1DhHtu 密码: ed4p

  • 相关阅读:
    iOS开发数据库篇—SQLite简单介绍
    iOS FMDatabase 本地数据库的创建和几个基本使用方法
    iOS开发-CoreMotion框架
    ios中陀螺仪CoreMotion的用法
    iOS摄像头和相册-UIImagePickerController-浅析
    iOS使用AVCaptureSession自定义相机
    在iOS上实现一个简单的日历控件
    iOS开发UI篇—Button基础
    在Virt-manager中使用snapshot功能
    Node.js学习
  • 原文地址:https://www.cnblogs.com/ShawnYang/p/6774297.html
Copyright © 2011-2022 走看看