事务隔离机制_悲观锁_乐观锁

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

时间: 2024-11-13 09:38:27

事务隔离机制_悲观锁_乐观锁的相关文章

第36讲 谈谈MySQL支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景

在日常开发中,尤其是业务开发,少不了利用 Java 对数据库进行基本的增删改查等数据操作,这也是 Java 工程师的必备技能之一.做好数据操作,不仅仅需要对 Java 语言相关框架的掌握,更需要对各种数据库自身体系结构的理解.今天这一讲,作为补充 Java 面试考察知识点的完整性,关于数据库的应用和细节还需要在实践中深入学习.今天我要问你的问题是,谈谈 MySQL 支持的事务隔离级别,以及悲观锁和乐观锁的原理和应用场景?典型回答所谓隔离级别(Isolation Level),就是在数据库事务中,

数据库事务的悲观锁和乐观锁

转载出处:http://www.hollischuang.com/archives/934 在数据库的锁机制中介绍过,数据库管理系统(DBMS)中的并发控制的任务是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性. 乐观并发控制(乐观锁)和悲观并发控制(悲观锁)是并发控制主要采用的技术手段. 无论是悲观锁还是乐观锁,都是人们定义出来的概念,可以认为是一种思想.其实不仅仅是关系型数据库系统中有乐观锁和悲观锁的概念,像memcache.hibernate.tair

一文带你理解脏读,幻读,不可重复读与mysql的锁,事务隔离机制

首先说一下数据库事务的四大特性 1 ACID 事务的四大特性是ACID(不是"酸"....) (1) A:原子性(Atomicity) 原子性指的是事务要么完全执行,要么完全不执行. (2) C:一致性(Consistency) 事务完成时,数据必须处于一致的状态.若事务执行途中出错,会回滚到之前的事务没有执行前的状态,这样数据就处于一致的状态.若事务出错后没有回滚,部分修改的内容写入到了数据库中,这时数据就是不一致的状态. (3) I:隔离性(Isolation) 同时处理多个事务时

mysql中的锁机制之悲观锁和乐观锁

1.悲观锁? 悲观锁顾名思义就是很悲观,悲观锁认为数据随时就有可能会被外界进行修改,所以悲观锁一上来就会把数据给加上锁.悲观锁一般都是依靠关系型数据库提供的锁机制,然而事实上关系型数据库中的行锁,表锁不论是读写锁都是悲观锁. 2.乐观锁? 乐观锁顾名思义,就是很乐观,每次自己操作数据的时候认为没有人会来修改它,所以不会去对数据进行加锁.但是在更新的时候会去判断在此期间数据有没有被修改,需要用户自己去实现乐观锁.乐观锁不会发生并发抢占资源,只有在提交操作的时候检查是否违反数据完整性. 2.1.为什

理解MySql事务隔离机制、锁以及各种锁协议

一直以来对数据库的事务隔离机制的理解总是停留在表面,其内容也是看一遍忘一边.这两天决定从原理上理解它,整理成自己的知识.查阅资料的过程中发现好多零碎的概念如果串起来足够写一本书,所以在这里给自己梳理一个脉络,具体的内容参考引文或在网上搜一下.由于平时接触最多的是MySQL,所以文章中某些部分是MySQL特有的特性,请读者注意. 数据库并发操作会引发的问题: 多个事务同时访问数据库时候,会发生下列5类问题,包括3类数据读问题(脏读,不可重复读,幻读),2类数据更新问题(第一类丢失更新,第二类丢失更

025 hibernate悲观锁、乐观锁

Hibernate谈到悲观锁.乐观锁,就要谈到数据库的并发问题,数据库的隔离级别越高它的并发性就越差 并发性:当前系统进行了序列化后,当前读取数据后,别人查询不了,看不了.称为并发性不好 数据库隔离级别:见前面章级 025-1悲观锁: 悲观锁:具有排他性(我锁住当前数据后,别人看到不此数据) 悲观锁一般由数据机制来做到的. 悲观锁的实现 通常依赖于数据库机制,在整修过程中将数据锁定,其它任何用户都不能读取或修改(如:必需我修改完之后,别人才可以修改) 悲观锁的适用场景: 悲观锁一般适合短事务比较

mysql-mysql悲观锁和乐观锁

1.mysql的四种事务隔离级别 I. 对于同时运行多个事务,当这些事务访问数据库中的相同数据时,如果没有采取必要的隔离机制,就会导致各种并发问题. (1)脏读: 对于两个事物 T1, T2, T1 读取了已经被 T2 更新但还没有被提交的字段. 之后, 若 T2 回滚, T1读取的内容就是临时且无效的. (2)不可重复读: 对于两个事物 T1, T2, T1 读取了一个字段, 然后 T2 更新了该字段. 之后, T1再次读取同一个字段, 值就不同了. (3)幻读: 对于两个事物 T1, T2,

悲观锁、乐观锁和数据库的锁之间的关系

首先悲观锁和乐观锁是基于业务逻辑来讲的,他们和数据库的锁是不同的概念,数据库的锁是实现数据库事务的机制. 乐观锁就在并发情况下,避免覆盖更新的一种机制,是程序员自己通过添加一个version字段实现,每次load数据都读出这个字段,在更新的时候比较下这个version字段是否一致而避免覆盖了不同的版本.至于他为什么叫乐观锁就是因为认为他的并发情况不高,即使发生并发导致更新失败也可以忍受.(适度控制并发,占用资源少,性能高,当然完全放任不管性能更高,根本不占用资源) 而悲观锁是基于数据库的锁机制来

数据库中的悲观锁和乐观锁详解

数据中的锁分为两类:悲观锁和乐观锁,锁还有表级锁.行级锁 表级锁例如: SELECT * FROM table WITH (HOLDLOCK) 其他事务可以读取表,但不能更新删除 SELECT * FROM table WITH (TABLOCKX) 其他事务不能读取表,更新和删除 行级锁例如: select * from table_name where id = 1 for update; 悲观锁(Pressimistic Locking) 对数据被外界(包括本系统当前的其他事务,以及来自