mysql乐观锁怎么写 炒股软件文字出现乱码怎么办?( 二 )


1、RC级别没有范围锁一定会导致不可重复读和幻影行
2、RR级别安全性更高 , 实现可重复读的方式为快照,如果需要最新数据可以选择[当前读],因此RR级别是首选
3、不论RR还是RC级别,增、删、改的操作都会进行一次[当前读]操作,以此获取最新版本的数据,并检测是否有重复的索引 。
4、RR级别下,当前事务如果未发生更新操作(增删改),快照版本会保持不变,多次查询读取的快照是同一个
5、RR级别下,当前事务如果发生更新(增删改) , 会刷新快照,会导致不可重复读和幻影行
6、RR级别下,使用当前读,会刷新快照,会导致不可重复读和幻影行
7、RR级别下,可以通过提交当前事务并在此之后发出新查询来为查询获取更新的快照 。
8、RR级别可以部分解决不可重复读和幻读问题
9、其实问题的关键是你的业务逻辑需要可重复读还是最新数据
为何Redis用乐观锁,而MySQL数据库却没有单来说,Redis使用乐观锁,相对于悲观锁,在实现中更加简单,在某些场景中的性能也更好 。Redis作为一个轻量级的、快速的缓存引擎 , 而不是一个全功能的关系型数据库,既没有使用悲观锁的必要,也难以承受使用悲观锁的成本 。
详细来说,要深入到Redis和MySQL的事务处理机制 。Redis关于事务的文档见此:
Transactions(事务)
Redis对于事务只提供了非常有限的支持,其实更多地是试图绕过问题 。
首先,Redis对于同一事务中的一组操作 , 而不是立即执行,而是放入一个queue中,当执行到EXEC时,再一起执行 。事务执行是全局独占的 , 也就是同一时间只有一个事务被执行,中途不能被其它事务打断 。Redis用这种最简单的、也是性能最差的方式避免了race condition 。
其次,在Redis的事务中,如果有一个或多个操作失败 , 其它操作仍然会成功,也就是说它根本没有回滚机制 。
这种方式会带来很多严重的问题,其中之一是,无法先读取某个数值后再进行依赖这个值的操作,因为放在一个事务里会被在同一个瞬间执行,不放在同一个事务里又会导致race condition 。解决方法是使用WATCH,它会监视一个或多个变量,如果变量的值在调用WATCH以后和事务提交之前被别的事务修改过了,整个事务都会失败 。这类似于操作系统中的CAS(Compare and Set) 。我不知道WATCH具体是怎么实现的 , 但是我推测它监控了指定变量的版本号 。
即使有了WATCH,Redis的事务也是受到严重限制的 。第一,它没有实现读数据时的一致性,因为WATCH对于读操作不起作用 。第二,它不支持回滚 。第三 , 在对同一变量存在大量并发写操作时 , 性能会非常差,因为每次提交事务时,WATCH监控的变量都已经被修改了,导致事务将多次提交失败 。但是 , Redis本来就是一个KV类型的缓存引擎 , 要处理的是大量读少量写的场景 , 对一致性也没有要求 。
MySQL就完全不一样了,作为一个典型的关系型数据库 , 它需要完整地实现ACID,所以Redis的方式是解决不了它的问题的 。
MySQL中的MVCC机制(Oracle的也是),通过undo 日志来获取某个行记录的历史快照,从而实现了所谓的读一致性 。它的目的是读取某个时间点上的历史数据(而不是可能已经被修改了的数据) , 而不是避免悲观锁的使用 。严格地说这不能称之为乐观锁,因为它既不Compare当前版本和历史版本,也不进行Set 。事实上 , 在读取记录的历史快照时,当前记录有可能(由于并发的写操作)已经被加上独占锁 。

推荐阅读