事务特性,事务的并发,事务隔离机制(乐观锁,悲观锁)
事务的四大特性
原子性(atomic):事务是不可分割的工作单元,对于数据的修改,要么都执行,要么都不执行。只有事务中的所有操作都成功了,才算完成整个事务,事务中的任何一个sql语句执行失败,那么成功的sql语句也必须撤销,数据库状态应该回到执行事务之前的状态。
一致性(consistent):事务完成时,必须使所有的数据都保持一致状态。数据库事务不能破坏关系数据的完整性一级业务逻辑上的一致型。了如银行转账事务,不管成功是否,应该保事务结束后两个转账账户的存款总额是一致的。
隔离性(insulation)事务的并发所修改必须和任何其他并发事务所作的修改 隔离。当不同事务同时操作相同的数据时候,每个事务都有各自的完整数据空间。
持久性(duration):事务完成之后,他对于系统的影响是永久性的。它对数据库所做的更新就必须永久保存下来。即使发生系统崩溃,重新启动数据库系统后,数据库还能恢复到事务成功结束时的状态。
事务的并发
为了获得更好的运行性能,各种数据库都允许多个事务同时运行,就是事务的并发
隔离机制
当并发的事务风闻或者修改数据库中的相同的数据(同一行同一列)必须采取隔离机制
解决并发的途径是: 有效的隔离机制
实现事务的隔离:实现必须用锁(悲观锁,乐观锁,MQ)
并发出现的问题
脏读:数据已修改事务没提交,另一事务读取到未提交的数据!(事务没提交另一事务就读到未提交的数据)
不可重复读:同一事务两次读取数据不一样;第一个事务读去数据,第二个事务修改数据提交,第一个事务再一次读取数据,这样第一个事务两次读取的数据将不一致。
幻读(虚读):两个事务,第一个事务将所有行的数据都修改了,第二个事务将插入一条数据提交,第1个事务提交发现有一条数据并没有修改。
第一类丢失(回滚丢失):
当2个事务更新相同的数据源,如果第一个事务被提交,而另外一个事务却被撤销,那么会连同第一个事务所做的跟新也被撤销。也就是说第一个事务做的跟新丢失了
1.2.5第二类更新丢失(覆盖丢失)
悲观锁
很悲观,总是假设最坏的情况,每次事务先获取锁,再进行业务操作。通常来讲在数据库上的悲观锁需要数据库本身提供支持,entityManager.find(class,id,LockModeType);即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,其他并发事务等待,上锁。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。
oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,mysql就没有no wait这个选项。另外mysql还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在mysql中用悲观锁务必要确定走了索引,而不是全表扫描。
乐观锁
乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。
乐观锁在数据库上的实现完全是逻辑的,不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:
// 添加一个私有字段Integer version,不由程序员维护,由JPA自己维护
@Version
private Integer version;
@Test
当然我们可以加一个finally关闭manager
MQ
队列消息也是解决高并发的问题 用来削峰的 详解到以后学了再说 听说很流弊的