事务的定义
事务(Transaction)是一个逻辑上完整的操作序列,它包含了一组数据库操作命令。这些操作要么全部执行成功,要么全部不执行,以此来维护数据库的一致性和完整性。事务的主要目的是确保数据的准确性,即使在出现错误或系统故障时也是如此。
事务的应用场景
- 金融交易:银行转账是最典型的事务应用场景之一,确保从一个账户扣除金额的同时,另一账户能相应增加金额,且整个过程不会因故障中断而导致资金丢失或重复记账。
- 库存管理:在线购物平台中,当用户下单购买商品时,系统需要确保库存减少和订单创建这两个操作作为一个整体执行,避免超卖或库存错误。
- 航空订票系统:机票预订过程中,座位的锁定和付款的确认必须作为一个不可分割的事务处理,以防止座位被重复预订。
- 酒店预订:确保房间预订和支付过程的完整性,避免房间被重复预定或支付后未保留房间的情况。
事务的四大特性
-
原子性,Atomicty,也就是我们刚才说的不可再分,也就意味着我们对数据库的一系列的操作,要么都是成功,要么都是失败,不可能出现部分成功或者部分失败的情况。以转账的场景为例,一个账户的余额减少,对应一个账户的增加,这两个一定是同时成功或者同时失败的。
全部成功比较简单,问题是如果前面一个操作已经成功了,后面的操作失败了,怎么让它全部失败呢?这个时候我们必须要回滚。
原子性,在 **InnoDB **里面是通过 undo log 来实现的,它记录了数据修改之前的值(逻辑日志),一旦发生异常,就可以用 undo log 来实现回滚操作。 -
一致性(Consisent) 事务的一致性是指在数据库管理系统中,事务的执行应当保证从一个一致性的状态转变为另一个一致性的状态。具体来说,这要求在事务开始之前和结束之后,数据库都保持着某种定义好的完整性约束和业务规则,确保数据的准确性和可靠性。
例如现在,用户A要向用户B转账100元。这个操作需要保持数据库的一致性,具体步骤可以分为以下几个事务内的操作:
1 开始事务:首先,数据库系统标记一个新事务的开始。
2 检查余额:系统检查用户A的账户余额是否足够进行这次转账。如果用户A的余额小于100元,则事务应该被回滚,以保持账户余额的准确性(一致性)。
3 扣款:如果用户A的余额足够,系统从用户A的账户中减去100元,并准备记录这一变化。
4 存款:同时,系统给用户B的账户增加100元。
5 记录交易:在Transactions表中添加一条新的交易记录,详细说明这次转账的信息。
6 提交事务:所有上述操作完成后,如果没有发生任何错误(比如并发事务导致的冲突),事务被提交。这时,用户A的余额减少和用户B的余额增加以及交易记录的创建都永久地保存到数据库中,整个数据库状态保持一致,即账户的总金额没有因为这次转账而改变,只是在不同账户之间重新分配。
7 事务失败处理:如果在执行上述任何一步骤时出现问题(比如系统崩溃),事务管理器会自动回滚事务,确保数据不被破坏,维持在事务开始前的一致状态。 -
隔离性,?
-
持久性,Durable,事务的持久性是什么意思呢?我们对数据库的任意的操作,增删改,只要事务提交成功,那么结果就是永久性的,不可能因为我们系统宕机或者重启了数据库的服务器,它又恢复到原来的状态了。这个就是事务的持久性。
事务的开启和提交
- 自动开启和提交:执行这样一条更新语句的时候,它有事务吗?
update student set name = '猫老公 11' where id=1;
事实上,它自动开启了一个事务,并且提交了,所以最终写入了磁盘。
这个是开启事务的第一种方式,自动开启和自动提交。 - 手动开启提交:todo
事务并发带来的问题
有很多人同时去操作数据库的同一张表,A更新了第一条数据,B准备读第一条数据,那么B读到的数据应该是A修改之前的数据还是A修改之后的数据?
引申出来的三个问题
- 脏读:
- 不可重复读:
- 幻读: