mysql之三范式简述
原子性(Atomicity):a向b转了十块钱,一定是a转出,b转入,不可能存在a转出,但b没有转入.(转账操作是一个不可分割的操作,要么转失败,要么转成功,不能存在中间状态,也就是转了一半的这种情况)【要么全做,要么全不做】
隔离性(Isolation):a向b转了十块钱,a向c转了十块钱,不可能出现b的账户里多了20块,即a转给c的,却转到了b的账户上。【两个操作互不影响】
一致性(Consistency):无论a,b之间如何转钱,A和b的总金额总是要保持不变的【最终数据一致性】
持久性(Durability):对于转账的交易记录,需要永久保存【事务提交后的数据要能永久保存】
事务(id为80),添加了数据1,并提交了。事务81,82,200都开启了事务并对数据1进行了相应的修改,但都未进行事务的提交(此时81,82,200都处于m_ids【他是readview里面的属性,是用来记录那些事务是活跃的】的数组里面),此时如果事务300过来了,它的事务隔离级别是读已提交,它会从上往下开始找寻版本链,发现200,82,81都在m_ids里面,所有都不会从里面读数据,往下走是80,它不在m_ids里面,故读到了80里面的数据1.
-[当前事物能够看到别的事物中未提交的数据(读的并不是最终数据),我们称这种现象为脏读]
张三开启事务:先将a设为5000,又将a设为2000,提交事务。
李四先读到了5000(脏读),又读到了2000
【脏读现象演示】
脏读:当前事务可以查看到别的事务未提交的数据(侧重点在于别的事务未提交).
不可重读(一次事务中两次对同一行数据读取出来,查询结果是不一样的)(数据读错了)
【不可重读现象演示】
不可重复读:不可重读的侧重点在于更新修改数据,表示在同一事务中,查询相同的数据范围时,同一个资源莫名的改变了。(mysql官方文档也把它归为幻读)
但是你可能会有个问题,事物的隔离性是由锁来实现的,事务1执行更新语句时,事务1中应该对数据增加了写锁【排他锁】,但在事务二中仍然可以进行查询操作?,可是写锁是排他锁,在事务1已经添加了写锁情况下,为什么事务二还可以读呢?这就与一致性非锁定读的机制有关,它提高了数据库的并发性,既【如果当前行被加了排他锁,那么当需要读取行数据时则不会等待行上的锁释放,而是会去读取一个快照数据】。
上图展示了innodb中一致性非锁定读的过程,之所以称其为非锁定读,是因为它不需要等待被访问行上的排他锁的释放,而上图中的快照的实现是由事日志所对应的undo来完成,其实快照就是该行对应的之前的版本的数据【即历史数据】,一行记录可能有不止一个快照数,并不是所有隔离级别都使用了一致性非锁定读,在“可重读和读已提交的级别下,innodb使用了一致性非锁定读,但是在这两个级别中,对于快照数据的定义也不相同,在可重级别下,快照数据是指当前事务开始时数据的样子,所以,在刚才的示例中,事务2中t1表对应的第二条记录的t1str的值一直都是2,因为在事务2开始的时候,其值就是2,这是其可重读的特性,但是在读提交的隔离级别下,由于对于快照的定义不同,所以显示的现象也不同。
【幻读现象演示】
幻读 :幻读的侧重点在于新增和删除,表示在同一事务中,使用相同的查询语句,第二次查询时,莫名的多出了一些之前不存在数据,或者莫名的不见了一些数据。
事务的隔离性是由锁来实现的
事务一更新表1数据时会施加写锁,事务二,对表一请求读锁时会被阻塞(出现请求锁超时的情况),只有当事务一提交了事务,他的锁释放了,事物二才能读出数据
它通过施加读写锁,虽然解决了幻读问题,但确使数据库失去了并发能力。