20hibernate hibernate的性能优化之事务并发和事务隔离机制

本文详细介绍了数据库事务的概念,包括ACID特性,并探讨了事务并发时可能遇到的问题及解决方案,如第一类丢失更新、脏读、不可重复读、第二类丢失更新和幻读。此外,文章还阐述了如何在Hibernate中设定事务隔离级别,以及使用悲观锁和乐观锁解决并发冲突的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

5.事务并发处理//面试的意义更大
	a.事务:
		是并发控制的单位,是用户定义的一个操作序列。
		这些操作要么都做,要么都不做,是一个不可分割的工作单位。
		通过事务,SQL Server能将逻辑相关的一组操作绑定在一起,
		以便服务器保持数据的完整性。
		
		事务四个特性:ACID
			(1)Atomicity	原子性
			//事务是数据库的逻辑工作单位,事务中包括的诸操作要么全做,要么全不做。
			(2)Consistency	一致性
			// 事务执行的结果必须是使数据库从一个一致性状态变到另一个一致性状态。
			//一致性与原子性是密切相关的。
			(3)Isolation	独立性
			//一个事务的执行不能被其他事务干扰。
			(4)Durability	永久性
			// 一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。

	b.事务并发时可能出现的问题
		(1)第一类丢失更新(lost update)--见图一
		//撤销一个事务覆盖了另一个已经提交事务
		//只有在不支持事务的数据库才会出现的问题
		(2)脏读(dirty read)--见图二
		//读到了另一个事务还没提交的数据
		(3)不可重复读(non-repeatable read)--见图三
		//被另一个事务影响,在一个事务中前后读取的数据不一致,不知道该用哪一个
		(4)第二类丢失更新(second lost update problem 不可重复读的特殊情况)
		--见图四
		//相当于还是前后读取的数据不一致
		(5)幻读(phamtom read)--见图五
		//在读的过程中,另一事务涉及到插入和删除的操作,影响了读取的结果
		
		面试掌握(2)(3)(5),是经常出现的问题

	c.数据库的事务隔离机制
		(1)四种隔离级别:(级别越高,效率越低,因为要检查要上锁)
			1.read uncommitted 
			//可以读取未提交的数据,会出现脏读、幻读和不可重复读问题
			//只要数据库支持事务,就不可能出现第一类丢失更新
			2.read committed (一般采用)
			//只有提交过的数据才能被读取,但不能避免不可重复读和幻读
			//并发性也比较好
			3.repeatable read
			//相当于在读取的数据上加把锁,这个事务没有结束前,别的事务不能修改该数据
			4.serializable(大多数情况下不会采用)
			//事务不能并发,排队进行

	d.设定hibernate的事务隔离级别
		(1)在hibernate.cfg.xml中设置hibernate.connection.isolation=2
			//取值有1,2,4,8(值是通过二进制设置的,算法效率高,通过左移右移可实现更改)
			//1是read-uncommitted;2是read-committed
			//4是repeatable read;8是serializable
			//不设的话,依赖于数据库
			//原则是尽量平衡并发和效率
		(2)用悲观锁解决repeatable read的问题(依赖于数据库本身的实现)
			1.select...for update
			2.load(xx.class,i,LockMode.Upgrade)//Upgrade的意思是让数据库加把锁
				a.LockMode.None 无锁的机制,Transaction结束时,切换到此模式
				b.LockMode.read 在查询的时候hibernate会自动获取锁
				c.LockMode.write insert update的时候hibernate会自动获取锁
				d.以上三种锁的模式,是hibernate内部使用的
				e.LockMode.Upgrade_NOWAIT oracle支持的锁的方式

			@Entity
			public class Account
			{
				private int id;
				private int balance;//涉及金额应采用BigDecimal
			}

			public void testPessimisticLock(){
				Session session = sf.openSession();
				session.beginTransaction();

				Account a = (Account)session.load(Account.class,1,LockMode.UPGRADE);
				int balance = a.getBalance();
				balance = balance-10;
				a.setBalance(balance);

				session.getTransaction().commit();
				session.close();
			}

	e.hibernate(JPA)乐观锁定(Read Committed)
		//采用@Version注解
		//悲观锁是借助数据库的锁,乐观锁是设置版本字段,
		//乐观锁通过比较版本来判断当前数据是否被更新过
		@Entity
		public class Account
		{
			private int id;
			private int balance;
			@Version
			private int version;
		}

		public void testOptimisticLock(){
			Session session = sf.openSession();
			Session session2 = sf.openSession();
			session.beginTransaction();
			Account a1 = (Account)session.load(Account.class,1);

			session2.beginTransaction();
			Account a2 = (Account)session2.load(Account.class,1);
			
			a1.setBalance(900);
			a2.setBalance(1100);
			
			session.getTransaction().commit();
			System.out.println(a1.getVersion());
			
			session2.getTransaction().commit();
			//此处会报错:Row was updated or deleted by another transaction
			System.out.println(a2.getVersion());
			
			session.close();
			session2.close();
		}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值