在并发场景下,并发执行事务的时候:
比如先执行的事务A要把商品库存数量从 0 修改成 1,然后又有一个事务B在执行时要读取商品的库存数量,这时候事务B读取到的商品库存数量为 1,事务B准备下一步要进行扣减库存数量了(但还未执行扣减);这时候,事务A回滚了,商品库存数量从 1 又变成了 0,这就会导致事务B中执行扣减库存的操作时出现问题。
这就出现了“脏读”。一个事务读取到了另一个事务没有提交的数据。所以,在并发执行事务的时候,多个事务之间应该要相互隔离,互不影响,否则就会出现问题。这就是事务的隔离性。
MVCC + 锁,再配合 undo log 来实现事务的隔离性
通过事务的隔离级别来应对。
数据库提供了四种事务的隔离级别:
如何实现:
MVCC:多版本并发控制。通过维护数据的多个版本来实现。
按照正常流程,只要保证了事务的原子性、持久性、隔离性,事务的一致性自然就实现了。
原子性:就是使代码逻辑(方法)中的多个执行sql的操作逻辑,要么全部成功,要么全部失败。
mysql的原子性如何实现呢?
可以通过undo log 回滚日志去实现。
比如,n个连续的sql操作中,失败了一个,通过undo log给前面已经执行成功的sql操作进行回滚。
事务提交后,数据库崩溃了,导致数据丢失了怎么办?此时就需要事务的持久性来保证。
持久性:只要事务一提交,无论发生什么事,数据库的修改(操作)都不会丢失。
如何实现持久性呢?
通过redo log来实现,每一次事务提交之后,就把这个修改的操作写入到redo log中,这样即便 mysql数据库中的旧数据还没有立马变成修改后的值,也能读取redo log来恢复数据。
换个角度,redo log 让mysql有了一定的崩溃恢复的能力。
事务的隔离性:针对并发执行事务的情况,多个事务之间应该相互隔离,互不影响。否则,就会出现问题。
在并发场景下,并发执行事务的时候:
比如先执行的事务A要把商品库存数量从 0 修改成 1,然后又有一个事务B在执行时要读取商品的库存数量,这时候事务B读取到的商品库存数量为 1,事务B准备下一步要进行扣减库存数量了(但还未执行扣减);这时候,事务A回滚了,商品库存数量从 1 又变成了 0,这就会导致事务B中执行扣减库存的操作时出现问题。
这就出现了“脏读”。一个事务读取到了另一个事务没有提交的数据。所以,在并发执行事务的时候,多个事务之间应该要相互隔离,互不影响,否则就会出现问题。这就是事务的隔离性。
MVCC + 锁,再配合 undo log 来实现事务的隔离性
一致性:无论事务最终执行结果是成功还是失败,执行成功后的结果和执行成功前的结果,数据是一致的;同理,执行失败也是。
比如,对于转账的业务来讲,在这个事务里,转账人要执行的是扣除转账金额(减少100)的操作,收款人要执行的是添加余额(添加100)的操作,无论事务是否成功,转账人和收款人的钱的总数,应该是保持不变的。
一致性如何实现呢?
按照正常流程,只要保证了事务的原子性、持久性、隔离性,事务的一致性自然就实现了。