悲观锁(MySQL 乐观锁)
悲观锁定是指对被外界修改的数据保持保守的态度,即在数据处理过程中锁定数据。这个功能需要依靠数据库提供的锁定机制,否则即使在系统中实现了锁定机制,也不能保证外部系统不会修改数据。
锁定模式
锁定模式。没有
无锁机构
锁定模式。阅读
Hibernate在读取记录时自动获取锁
即共享锁(s锁),也称为读锁。如果事务T获得了数据对象A上的共享锁(即把共享锁加到A上),那么其他事务只能获得A上的共享锁(S锁),而不能增加排他锁(X锁),直到A释放所有的共享锁。允许共享锁的事务只能读取数据,但不能修改数据。
锁定模式。写
Hibernate在插入更新记录时自动获取锁
也就是排他锁(x锁),排他锁也叫写锁。如果事务t获得了数据a的排他锁,那么t可以读写a,但是在t释放a的x锁之前,其他事务既不能获得a的共享锁,也不能获得a的排他锁。
锁定模式。升级
如果数据库系统支持悲观锁(如Oracle和MySQL),则执行select…for update语句(行级锁,其他事务不能更新,插入和删除语句),如果数据库不支持悲观锁(如Sybase),则执行普通select语句。
锁定模式。UPGRADE_NOWAIT
和锁定模式。升级具有相同的功能。此外,为Oracle数据库执行select…for update nowait语句。“nowait”意味着如果执行select语句的事务不能立即获得悲观锁,它将不会等待其他事务释放锁,而是立即抛出锁异常。
锁的演示
注意:Lock只对一个事务中操作的数据对象起作用,而不是对整个数据库起作用,而是锁定整个数据库。
打开两个SQL命令行操作界面,可以代表两个事务T1和T2。我们首先在两个接口上执行命令:启动事务;
在事务T1中,查询数据库中学号为“2015”的学生信息,并对操作数据添加悲观锁:从stu _ info中选择*进行更新,其中stu _ no =“2015”;。此时,我们可以查询相应的信息。
“for update”表示添加悲观锁。在这个查询之后,事务没有被提交,即锁没有被释放
在交易T2中,查询数据库中学号为“2016”的学生信息,并将悲观锁添加到操作数据中:从stu _ info中选择*进行更新,其中stu _ no =“2016”;。这时,我们也可以查询相应的信息。
交易尚未提交
在交易T2中,查询数据库中学号为“2015”的学生信息。这次做一个普通的不加锁的选择查询:从stu _ info中选择*其中stu _ no = " 2015。这时,我们也可以查询相应的信息。
交易尚未提交
在交易T2中,尝试查询数据库中学号为“2015”的学生信息,并在操作数据中添加悲观锁:从stu _ info中选择*进行更新,其中stu _ no =“2015”;。这时我们可以发现,相关信息并没有显示,而是在等待。当我们提交事务T1(即commit)时,数据对象“2015”在T1中释放悲观锁,T2事务可以查询相关信息,获得悲观锁。
如果我们改变第五步。在刚才的第五步中,我们在没有悲观锁的情况下修改了事务T1中学号为“2016”的学生信息,因为我们之前在事务T2中为该记录添加了悲观锁,并且该记录尚未发布,所以我们只能在T2提交后才能成功修改。
推荐教程:MySQL教程