事务特性(ACID)
-
原子性:
所有步骤要么都执行,要么都不执行,一旦在某个步骤出现错误,则需要进行回滚。 -
一致性:
保证数据的正确性:例如:A给B转账100,则在转账之后与转账之前数据应该保持正确(A,B总金额前后一致),保证业务数据不能出错。 -
隔离性:
当多个用户同时操作同一张数据表时,数据库需要为每个用户开启一个事务,保证多用户之间的操作不能被其他用户干扰,多个事务之间互相隔离。
例如:在A,B两个并发的事务中,在事务A看来,事务B已经执行结束或者还没有开始执行,在事务B看来,事务A已经执行结束或者还没有开始执行,类似于一种排队执行的思想。 -
持久性
一旦事务提交成功,则会将数据保存到数据库中。
例如:当转账成功,两个账号的金额会发生变化,则会将金额保存到数据库中永久保存。数据备份多个。
我们先看一下数据库的隔离级别:
修改隔离级别的语句:set global transaction isolation level 隔离级别
查看隔离级别:select @@tx_isolation
mysql默认采用repeatable read重复度隔离级别。
oracle默认采用read committed读已提交的隔离级别。
什么是脏读?
如果两个事务并发执行,一个事务读取了另一个事务没有提交的数据。事务B读取事务A执行的表,然后事务A回滚,事务B则读出的数据时脏数据,称为脏读。
什么是不可重复读
事务A多次读取同一个数据,事务B在事务A多次读取数据的时候,对数据进行修改,导致事务A多次读到的数据不一致。
什么是幻读?
事务A与事务B同时操作一张表,事务A对该表的增加或删除操作,事务B是读不到的,类似于事务B在读数据之前对该表增加了一个标记,标记该表只能读取到该标记的位置,后面数据表发生改变则读取不到。导致读取的数据与数据表的数据不一致。
不可重复读侧重对数据库的修改,幻读侧重对数据库的增加,解决不可重复读需要锁满足的条件,幻读我们需要进行锁表。
隔离级别的效率:
读未提交的(read uncommitted)> 读已提交的(read committed)> 不可重复读(repeatable read)> 串行化(serializable)
数据库中如何实现隔离级别
-
读未提交:性能最高,路子最野,压根没加锁,所以没有任何隔离效果,我们可以认为它什么也没有做。
-
读已提交:先对读未提交的数据后面加上commit,解决读脏数据的问题。
两个事务对同一个数据进行修改,数据最终结果与最后一个修改的一致。当事务A对该数据进行修改时,会加锁,这时如果事务B也想对该数据进行修改则阻塞等待,当事务A对该数据修改完后,释放锁资源,事务B得到锁资源对数据进行修改,但是事务B阻塞等待时会有一个默认等待时间,如果超过该等待时间则超时等待,需要重新对该表进行操作。 -
可重复读:为了实现可重复读,MySQL采用多版本并发控制。
-
串行化:读的时候加共享锁,表示其他事务只能读,但是不能进行修改,写的时候加排它锁,表示其他事务不能读不能写。