先来说说自己对事务的理解。
首先自己对事务的理解就是数据库中一个个完成的事件,我们在每次执行数据库的操作的时候,其实就是完成了一个事务,其实我们在平时使用数据库的时候,就已经在使用事务了。因为数据库默认是自动commit的,所以我们每执行一次操作,便会自动提交事务。所以这里的重点其实是对事务的理解。以及手动commit事务的一些用法以及其作用。
首先是事务的ACID特性
即原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
原子性指事务中的操作要么全部完成,要么全部失败撤销
一致性指事务中的操作都是在逻辑上正确的。
隔离性指多个事务之间不互相干扰,并发的事务之间要相互隔离。
持久性是指事务一旦提交,对数据库的操作就是永久性的。
事务的使用
想要控制事务的话,就需要关闭自动提交,这里有两种不同的方式来控制
首先是start transaction
它的意义是开始一个事务,在这个语句之后的操作都属于这个事务之内的,只有在commit之后这些数据才会生效,而使用rollback后就会回滚。回到start transaction语句之前的状态。
另一种就是set autocommit=0
使用这个语句之后就会将当前的模式转换为手动提交,在这之后的所有sql语句,都需要commit之后才会永久性的提交
这里需要注意的是两者的差别,start transaction是不管之前是否设置set autocommit,它都会开始一个手动提交的新事务,直到commit之后,才会生效,rollback之后就会回滚。在commit或者rollback之后,autocommit会自动还原到start transaction之前的状态。
在事务中还可以通过插入保存点来还原到保存点之前的状态,创建保存点的方法是SAVEPOINT point_name
删除是RELEASE SAVEPOINT point_name
回到保存点之前的状态是ROLLBACK TO SAVEPOINT point_name
例如之前作业里的表,我们查询分数
新建事务,对分数进行两次修改,并在中间设置存档点并返回存档点 image
image 可以看到数据回到了存档点之前的修改
接下来是事务当中概念较难理解的隔离性
首先,需要了解没有隔离性所会发生的几种问题
1、脏读(Dirty Read)
一个事务处理过程里读取了另一个未提交的事务中的数据
2、不可重复读(NonRepeatable Read)
对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询的间隔期间,另外一个事务修改并提交了该数据
3、幻读(Phantom Read)
在一个事务中读取到了别的事务插入的数据,导致前后不一致
在事务中有四个隔离级别,它们对这3种问题的解决方法用一张图来展示 image
当需要查看当前事务的隔离性是哪个等级的时候,可以使用SELECT @@transaction_isolation命令来查看 image
要修改当前事务的隔离性等级的时候,使用
SET session TRANSACTION ISOLATION LEVEL 隔离等级
如 image
我们来实际测试一下它的隔离性
我使用了之前作业里的score表
首先新建两个事务
我们在这个事务中查询分数
image
在第二个事务中将所有的分数都加上了20
image
再次查询,发现并没有查询到事务2中所做的改变
image
查询隔离性
image
发现系统默认的是REPEATABLE READ, 因为这种隔离方式不支持脏读,所以没有办法读取到事务2中的改变
我们重新开始一个事务,并将隔离等级改为READ UNCOMMITED
再继续新建事务2,修改表中数据
image
这次再在事务1中查询,发现可以查询到变化了
image
接下来还可以尝试不可重复读的效果
在事务1中将隔离等级设置为REPEATABLE READ,并查询成绩
image
在事务2中修改值并提交,查看到值已改变
image
再回到事务1中查询,发现并没有随着变化
image
在事务1中再次执行成绩加20的操作,并查看值
image 可以发现并不是只加了20,事务2的修改也表现了出来,数据的一致性倒是没有被破坏。select操作不会更新版本号,是快照读(历史版本);insert、update和delete会更新版本号,是当前读(当前版本)。
mysql中事务隔离级别为serializable时会锁表,插入记录会显示报错,因此不会出现幻读的情况,这种隔离级别并发性极低,开发中很少会用到。
隔离级别越高,越能保证数据的完整性和一致性,但是对并发性能的影响也越大。
网友评论