举很好的例子:https://blog.youkuaiyun.com/jiesa/article/details/51317164
脏读,幻读,不可重复读: https://www.cnblogs.com/sushu-yaya/p/6944287.html
(根据自己的理解画的一个图,AB代表两个事物)
1.脏读(Dirty Read)——一个事务(A)读取到了另外一个事务(B)没有提交的数据。单B是有可能rollBack的,如果B rollBack,A读到的就是无用的数据。
2.幻读(Phantom)——同一事务中,用同样的操作读取两次,得到的记录数不相同。事务A查询所有记录数量,事务B insert一条数据,事务A再次查询,发现不一致。
幻读发生在当两个完全相同的查询执行时,第二次查询所返回的结果集跟第一个查询不相同。
注意:幻读重点在新增或删除。
3.不可重复读(Nonrepeatable Read)——在同一事务中,两次读取同一数据,得到内容不同
注意:不可重复读重点在修改。
4.丢失更新 (Lost Update)
事务T1读取了数据,并执行了一些操作,然后更新数据。事务T2也做相同的事,则T1和T2更新数据时可能会覆盖对方的更新,从而引起错误。
==========================================================================
解决脏读:
修改时加排他锁,直到事务提交后才释放;读取时加共享锁,这样在事务1读取数据的过程中,其他事务就不会修改该数据。
解决不可重复读:
1) 推迟事务2的执行,直至事务1提交或者回退。这种策略在使用锁时应用。
2) 而在多版本并行控制中,事务2可以被先提交,而事务1继续执行在旧版本的数据上。当事务1终于尝试提交时,数据库会检验它的结果是否和事务1、事务2顺序执行时一样。如果是,则事务1提交成功;如果不是,事务1会被回退。
解决幻读:
实行序列化隔离模式,在任何一个低级别的隔离中都可能会发生。
处理以上隔离级别的问题,采用如下方法:
事务隔离五种级别:
(1)TRANSACTION_NONE 不使用事务。
(2)TRANSACTION_READ_UNCOMMITTED 允许脏读。
(3)TRANSACTION_READ_COMMITTED 防止脏读,最常用的隔离级别,并且是大多数数据库的默认隔离级别。
(4)TRANSACTION_REPEATABLE_READ 可以防止脏读和不可重复读。
(5)TRANSACTION_SERIALIZABLE 可以防止脏读,不可重复读取和幻读,(事务串行化)会降低数据库的效率。
以上的五个事务隔离级别都是在Connection接口中定义的静态常量,使用setTransactionIsolation(int level) 方法可以设置事务隔离级别。
如:con.setTransactionIsolation(Connection.REPEATABLE_READ)。
注意:事务的隔离级别受数据库的限制,不同的数据库支持的的隔离级别不一定相同。
https://blog.youkuaiyun.com/jiesa/article/details/51317164
========================================================================
MySql各种锁
乐观锁:读取数据的时候不加锁,提交数据的时候判断是否数据有修改,如果有就rollBack。通过设置版本号或者时间戳来实现。
悲观锁:读和写的时候都加锁。
从读写角度:分共享锁(S锁,Shared Lock)和排他锁(X锁,Exclusive Lock),也叫读锁(Read Lock)和写锁(Write Lock)。
持有S锁的事务只读不可写。如果事务A对数据D加上S锁后,其它事务只能对D加上S锁而不能加X锁。
持有X锁的事务可读可写。如果事务A对数据D加上X锁后,其它事务不能再对D加锁,直到A对D的锁解除。
从锁的粒度角度:主要分为表级锁(Table Lock)和行级锁(Row Lock)。
Spring隔离级别
从ACID,到脏幻不可重复,到各种锁,到springTransactional,写的非常棒:
https://www.cnblogs.com/yldIndex/p/spring_Transactional.html