事务的四大特性以及隔离级别详解

事务的四大特性(ACID)

今天操作Mysql数据库的时候突然想起了事务,然后就有了现在,首先我们来谈谈事务的四大特性吧。

1. 原子性(Atomicity)
所谓事务的原子性,用一句话概括就是指的是事务中包含的所有操作,要不全部成功要不全部失败并回滚。事务是数据库的逻辑和工作单位。
2. 一致性(Consistency)
然后是事务的一致性,指的是事务必须从一个一致性状态转换到另一个一致性状态,通俗的说就是一个事务执行前后都必须是一致性状态。
举个栗子:小明和小红之间总共有520元钱,无论他们彼此转账多少次,各自持有多少元钱,最终还是520元钱。
3. 隔离性(Isolation)
然后隔离性指的是多个用户并发访问数据库时,比如操作同一张表时,数据库为每一个用户开启的事务,不能被其他事务所干扰,多个并发事务之间要相互隔离。
即达到这么一个效果->并发事务S1和S2,在事务S1看来,事务S2要么在事务S1执行之前就已经结束了,要么在事务S1执行结束之后才开始;S2亦同理。这样一来每个事务都感觉不到有其他事务并发执行。这里涉及到事务的隔离级别,后面再说。
4. 持久性(Durability)
最后一个特性,持久性指的是事务一旦提交,他对数据库中数据的改变是永久性的,接下来的其他操作或故障不应对其执行结果产生任何影响。
好了,以上就是事务的四大特性,简称ACID。

事务的隔离级别

首先,有必要了解一下 什么是事务的隔离级别
事务隔离是数据库事务处理的一个基础。在数据库操作中,当有多个改变事务进行,同时又有多个查询事务进行时,这时候就需要设置一个东西对结果进行调节以保证结果的正确性,这个设置的东西就是事物的隔离级别。
那么, 事务隔离级别的主要作用是什么呢?
事务隔离级别主要是用来解决事务并发执行时所引发的一系列问题的。
如果事务没有设置任何隔离级别,那么将会发生以下问题:
一、读的问题
1.脏读
指一个事务读到了另一个事务未提交的数据。(针对未提交的数据)
举个栗子:张三查询数据库看到了小明的age是12,这时候李四将小明的age执行update操作变成了15,但是并没有commit,这时候张三再次查看小明的age,结果变成了15,导致前后两次读取数据不一致,这就是脏读。
简单的说一个事务读到了另一个事务已经修改但是并未提交,最后反而回滚了的数据。
2.不可重复读 (针对提交前后数据本身的对比)
指一个事务读到了另一个事务已经提交的数据,导致多次查询结果不一致。
举个栗子:张三查询数据库看到了小明的age是12,这时候李四将小明的age执行update操作变成了15,并且commit,这时候张三再次查看小明的age,结果变成了15。这就是不可重复读
3.幻读(虚读) (针对提交前后数据条数的对比)
指一个事务读到了另一个事务插入的数据,导致多次查询结果不一致。
举个栗子:算了,不举了,自己体会~~~

幻读和不可重复读的区别:
其实不可重复读和幻读很相似,只不过不可重复读针对的是对数据的update操作,而幻读针对的是对数据的insert操作。前者是数据条数不变,但是数据本身变化了;后者是数据条数变化了,但是数据本身不变。

那么,为了解决以上问题,就得设置事务的隔离级别了。
Mysql数据库支持四种隔离级别(默认为第三种) ,隔离级别从低到高以及能解决的问题如下所示:

  • 读未提交(Read uncommitted) -> 任何问题都无法解决;
  • 读已提交(Read committed) -> 可解决脏读的问题,即可避免脏读;
  • 可重复读(Repeatable read) -> 可解决脏读和不可重复读的问题;
  • 序列化(Serializable) -> 可解决脏读、不可重复读、幻读的问题。

以上四种隔离级别按照功能排序是从低到高,但是按照效率排序是从高到低,刚好相反。
这里在提一嘴,Oracle数据库只支持2和4两种隔离级别,默认为2。
然后是 如何查看以及设置事务的隔离级别

select @@tx_isolatiion;							//查看事务的隔离级别
//设置事务的隔离级别,根据实际需要设置,修改level后面的字段即可
set session transaction isolation level read committed;		

二、写的问题
ok,说完读的问题,在简单了解一下写的问题。
其实写的问题就一个,那就是 丢失更新。所谓丢失更新,指的是一个事务修改数据库的时候,另一个事务也在修改数据库,那么,最后一个事务无论是提交还是回滚,都会造成前一个事务的数据更新丢失。
那么,如何解决写的问题呢?那就是加锁,悲观锁或者乐观锁。

悲观锁: 还没干活就想着会出错,查询数据的后面跟上关键字for update;

乐观锁: 程序员自己控制,在表里面增加一个字段version(版本的意思),默认为0,每次操作,则递增。下次操作时,先核对版本号,如果对不上,则表示是旧的数据,得先查询再操作数据。

over,如果不当之处,欢迎拍砖~

猜你喜欢

转载自blog.csdn.net/qq_42815754/article/details/83034218