好记忆也需烂 2020-05-10
事务分为三个主要知识点,分别是基本属性,并发事务处理带来的问题,以及事务的隔离级别。
事务是一个原子操作单元,其对数据的修改,要么全都执行,要么全不执行
在事务开始和完成时,数据都必须保持一致状态,这意味着所有相关的数据规则都必须应用于事务的修改,以保持数据的完整性
数据库系统提供一定的隔离机制,保证事务在不受外部并发操作影响的独立环境执行
事务完成之后,它对于数据的修改是永久性的,即使出现系统故障也能够保持
概念:当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题,即最后的更新覆盖了由其他事务所做的更新
常见场景:update
概念:一个事务读取另一个事务未提交的数据:事务1读取一条数据并做了修改,此时事务2读取事务1已修改且未提交的数据;此时如果事务1回滚了修改操作,那么事务2读取的数据就是脏数据
常见场景:回滚
概念:一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了。这种现象就叫做不可重复读。也就是说,事务A读取到了事务B已经提交的修改数据,不符合隔离性。
常见场景:update或delete
概念:一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象被称为幻读。也就是说,事务A读取到了事务B提交的新增数据,不符合隔离性
常见场景:insert
事务隔离级别是为了避免上述并发事务处理所带来的问题的。
指的是一个事务读取到另外一个事务还没有提交的内容。这种情况是必须要避免的。因为其他事务未提交的数据,是随时有可能进行回滚的,所以,任何时候,都不应该允许程序读取到某个事务还未提交的数据。如果读取到了别的事务未提交的数据,这种情况称为脏读。要想解决脏读的问题,可以提高数据库的事务隔离级别,把事务隔离级别设置为读已提交。
这个隔离级别可以解决脏读的问题。
在该隔离级别下,不允许2个未提交的事务之间并行执行,但它允许在一个事务执行的过程中,另外一个事务得到执行并提交。这样,会出现一种情况,第一个事务前后两次select出来的某行数据,值可能不一样。值改变的原因是,穿插执行的事务2对该行数据进行了update操作。在同一个事务中,两次select出来的值不相同的问题称为不可重复读问题。要想解决不可重复读问题,需要把数据的隔离级别设置为可重复读。
在这个隔离级别下,可以解决不可重复读的问题。
在该隔离级别下,在一个事务使用某行的数据的过程中,不允许别的事务再对该行数据进行操作。可重复读应该是给数据库的行加上了锁。这种隔离级别下,依旧允许别的事务在该表中插入和删除数据,于是就会出现,在事务1执行的过程中,如果先后两次select出符合某个条件的行,如果在这两次select直接另一个事务得到了执行,insert或delete了某些行,就会出现先后两次select出来的符合同一个条件的结果不一样,第一次select好像出现了幻觉一样,因此,这个问题也被成为幻读。要想解决幻读问题,需要将数据库的隔离级别设置为串行化。
串行化可以解决幻读的问题。
它要求事务的执行完全串行执行。所以失去了并发的效率。
Mysql的默认隔离级别为可重复读。
数据的事务隔离级别分为4种,从低到高依次为读未提交,读已提交,可重复读,串行化。
与数据库事务隔离级别相关的问题有3个,分别是脏读,不可重复读,幻读。
脏读问题需要用读已提交来解决,但读已提交会存在不可重复读问题。
不可重复读问题需要用可重复读来解决,但可重复读会存在幻读问题。
幻读问题需要用串行化来解决。