什么是事务?
事务,即数据库事务。是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
通常,事务的正确执行会使数据库从一种状态转换为另一种状态。
事务的特性(ACID原则)
原子性(atomicity) 即不可分割性,事务要么全执行、要么全不执行。
一致性(consistency) 事务的执行使得数据库从一种正确状态转换成另外一种正确状态。
隔离性(isolation) 在事务正确提交之前,不允许把事务对该数据的改变提供给任何其他事务。
持久性(durability) 事务正确提交之后,其结果将永远保存在数据库之中。
并发状态下事务会产生的问题
并发状态解释为当事务A和事务B对同一资源进行操作时,可能会遇到很多的问题。
脏读(针对未提交数据)
即事务A读到了事务B还没有提交的数据。如果事务A对数据进行了更新,但是事务A并没有提交,但是事务B这个时候看到了事务A没有提交的更新。当事务A进行了回滚,那么刚刚事务B看到的数据就是脏数据。也就是脏读。
例子:
A 给 B 转了100万,但是 A 还没有提交,此时 B 查询自己账户,多了100万。然后 A 发现转错人了,回滚了事物。然后 B 100万就没了。在这个过程中 B 查到了没有提交的数据(多出的100万),这就是脏读。
不可重复读(在一个事务里面读取了两次某个数据,读出来的数据不一致,针对修改操作)
即同一事务在事务执行过程中对同一个数据进行了多次读取,但是每一次读取的数据结果都不相同。原因是在两次读取间隔,数据别其他人修改了,导致了统一事务两次读取结果不一致。
例子:
A 查询银行余额为100万,B 这个时候取走了50万,此时余额变成了50万,A 再一次查询余额,变成了50万。对 A 而言两次结果不一致就是不可重复读。
幻读(在一个事务里面的操作中发现了未被操作的数据,针对增删操作)
即在事务 A 多次读取数据集的过程中中,事务 B 对数据进行了新增操作或者删除操作,导致事务 A 多次读取的数据集不一致。
例子:
A 修改当前公司所有职员信息的时候,B 向其中插入了一个新的职员,这个时候 A 提交的时候发现了一个自己没有修改过的职员的信息,对 A 而言就像是产生了幻觉。
事务的隔离级别
为了应对上面并发情况下出现的问题,事务的隔离级别就产生了。当事务的隔离级别越高的时候,上面的问题就会越少,但是性能消耗也会越大。所以在实际生产过程中,要根据需求去确定隔离级别。
四种隔离级
READ_UNCOMMITTED
读未提交,即能够读取到没有被提交的数据,所以很明显这个级别的隔离机制无法解决脏读、不可重复读、幻读中的任何一种。
READ_COMMITED
已提交,即能够读到那些已经提交的数据,能够防止脏读,但是无法解决不可重复读和幻读的问题。
REPEATABLE_READ
重复读取,即在数据读出来之后加锁,类似"select * from XXX for update",明确数据读取出来就是为了更新用的,所以要加一把锁,防止别人修改它。REPEATABLE_READ的意思也类似,读取了一条数据,这个事务不结束,别的事务就不可以改这条记录,这样就解决了脏读、不可重复读的问题,但是幻读的问题还是无法解决。
SERLALIZABLE
串行化,最高的事务隔离级别,不管多少事务,挨个运行完一个事务的所有子事务之后才可以执行另外一个事务里面的所有子事务,这样就解决了脏读、不可重复读和幻读的问题了。
如有收获,请帮忙转发,您的鼓励是作者最大的动力,谢谢!
一大波微服务、分布式、高并发、高可用的原创系列文章正在路上,
欢迎关注头条号:java小马哥
周一至周日早九点半!下午三点半!精品技术文章准时送上!!!
十余年BAT架构经验倾囊相授