JDBC
声明:本栏目所使用的素材都是凯哥学堂VIP学员所写,学员有权匿名,对文章有最终解释权;凯哥学堂旨在促进VIP学员互相学习的基础上公开笔记。
1.高级锁读取方式
悲观锁是系统自己增加的锁,乐观锁是程序员用程序逻辑来自己设计的一种锁机制。
怎么查看事务的隔离级别:
命令:select @@tx_isolation 查出来的隔离级别如上:
REPEATABLE-READ:这种隔离级别是不会出现脏读现象的。
要实现脏读这个现象,要设置隔离级别为:读取未提交内容
set session tx_isolation=’read-uncommitted’:
设置好读取未提交内容这个隔离级别以后,我们在事务A中把表的数据改为789,并没有提交,但是在事务B中,查出来的确是789,说明可以读取到没有提交的事务。
在这种隔离级别下,是很容易造成问题的:比如,bankid里面,发工资了,但是不确定要发多少。在事务A中先发10000,不提交(因为没有确认),然后事务B查看,发现金额有10000,(这种隔离级别下能读取未提交的内容),但是事务A发现不应该发10000,所以rollback一下,然后事务B再去查看的时候,发现10000没了。这就是脏读现象了:
如果想避免脏读现象的发生,要改变隔离级别为read-committed,只读取提交的内容这种隔离级别。
很多时候,人们设置读取未提交内容这个隔离级别,是为了加快读取的速度而冒着产生脏读这种现象的风险的。可见脏读读取的数据是无意义的,是无效的,为了防止这种问题,我们要设置隔离级别为只读取提交的内容。
不可重复读:当一个事务多次读取的时候,发现数据有变化,但是又不知道这个数据是不是确定的,不知道它会不会再改,这种现象也是在读取未提交内容这个隔离级别下产生的。
怎么防止这种现象发生:
将隔离级别设置为repeatable-read这种,然后就发现事务B中修改的金额(未提交事务),在事务A中读取多少次都是不会变的。默认的隔离级别就是这种隔离级别。上面四种级别,可以自己更换。这种默认的隔离级别,可以防止脏读和不可重复读,但是防止不了幻读。
幻读:先设置隔离级别为:read-uncommitt,然后这种现象就是:事务A先查看了一下数据,然后它想把所有数据中的金额上调1000,然后事务B插入一条数据,没有1000那么多,比如10或者20,然后事务A再查看数据的时候,发现多了一条数据记录,但是是没有加1000的,事务Brollback一下,然后事务A不知道这个操作,它还以为有两条数据,于是又把数据中金额上调1000,再查看的时候,第一条数据相当于上调了2000.:
要防止幻读,就要设置隔离级别为:serializable:
幻读就是,用户A一开始读出来的几条数据,我将它修改了一下,然后别的用户B新增了几条数据,用户A再次进行读取的时候,发现有几条数据没有修改到,这就像发生了幻觉一样。
为啥设置隔离级别:一般,我们上锁的话,别的事务是无法进行修改的,也有一些连读也读不成。
有些业务上,需要发生某些现象,比如卖火车票的时候,需要发生幻读:事务A,最开始想买三张票,查出来三张票,则系统就要保证这查出来的三张票要能够卖给事务A,不能你查出来后,下一秒付款的时候,发现又买不了了。所以我们一查出来,就要把三张票标记为已售,但具体买几张,看实际情况,比如事务A后面只买了一张,那就要把另外两张没有买的还原为未售的状态,这时,在事务B的眼中,最开始的时候,被事务A查出的三张票是查不到的,但是后面等A买完后,发现又多了两张票可以查到了,这就相当于幻读的现象了。
这里要使用隔离级别而不要使用锁,上锁的话,是会读取到别的用户打算购买的票的。
这种方法能确认你只要查的出来就能买的着,这就是为啥买票的时候会有一直刷的情况。
用图形化,做一个例题:
用Swing画一个图形窗口,如上图所示.
票务数据的代码设计如上。
查询票务的事件代码如上。
如上图所示,查询后,就把查询出来的票的状态改为0了,但是此时还没有提交事务,并且这里能读取未提交的内容。
上面是取消查询和确认购买的事件代码。
如上图,选定的4、5、6、7四张票就会被占住,状态被改为已售了。
点击取消查询后,进行了回滚,则5、6、7三张票的状态又变为待售了。
程序一断开,所做的操作全部会回滚。
脏读、不可重复读、幻读,这些现象都是可以使用到某些业务上去的。业务要选择不同的隔离级别,来符合实际的逻辑情况。