数据库事务其实实现还是蛮复杂的,现在在单应用的情况下,简单的多了。
隔离级别,用默认的;事务开启提交:用Spring注解。这样就已经满足大多数场景了,甚至传播行为也都是默认的。
而分布式的情况下也很少依赖数据库分布式事务,也都是基于其他条件完成。
正因为这样,很多人不去花心思了解,甚至八股文都没有背全面,面试容易挂掉,记一记还是大有好处。
至于MVCC事务实现方式也比较重要,后面讲。
1. 什么是数据库的事务?(ACID特性)
数据库事务是指一组数据库操作,这些操作要么全部成功执行,要么全部失败回滚,事务可以确保数据库的一致性和完整性。
在MySQL中,事务是由一系列SQL语句组成的逻辑工作单元。事务具有以下四个特性(ACID特性):
原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,不会出现部分执行的情况。
一致性(Consistency):事务执行前后,数据库的状态必须保持一致。如果事务执行失败,数据库会回滚到事务开始前的状态。
隔离性(Isolation):事务的执行是相互隔离的,一个事务的操作不会被其他事务所干扰。事务之间的操作可以并发执行,但是结果必须与串行执行的结果一致。
持久性(Durability):一旦事务提交成功,其结果将永久保存在数据库中,即使系统发生故障也不会丢失。
在MySQL中,可以使用 BEGIN
、COMMIT
和 ROLLBACK
语句来控制事务的开始、提交和回滚。通过使用事务,可以确保数据库操作的一致性和完整性,同时提高并发性能。
之前存储引擎篇反复提到了,目前Innodb支持事务,其他的存储引擎不支持。
2. 数据库的事务隔离级别有哪些?
MySQL数据库的事务隔离级别有以下四种:
读未提交(Read Uncommitted):事务中的修改可以被其他事务立即看到,可能会导致脏读、不可重复读和幻读的问题。
读已提交(Read Committed):事务中的修改只有在提交后才能被其他事务看到,可以避免脏读的问题,但仍可能出现不可重复读和幻读的问题。
可重复读(Repeatable Read):默认级别,事务中的查询结果保持一致,即使其他事务对数据进行了修改,也不会被当前事务看到。可以避免脏读和不可重复读的问题,但仍可能出现幻读的问题。
串行化(Serializable):事务串行执行,可以避免脏读、不可重复读和幻读的问题,但会降低并发性能。
不同的隔离级别会对并发性能和数据一致性产生影响。隔离级别越高,数据一致性越好,但并发性能越差。而隔离级别越低,并发性能越好,但数据一致性可能会受到影响。因此,在选择隔离级别时需要根据具体的业务需求和性能要求进行权衡。
3. Mysql默认是哪种隔离级别?
MySQL默认的隔离级别是可重复读(REPEATABLE READ),通过下面sql可以查看当前隔离级别。
SELECT @@tx_isolation;
MySQL选择可重复读作为默认的隔离级别,主要是为了保证数据的一致性和避免脏读、不可重复读的情况。
对于幻读来说,一般系统要求并没有那么高。
也就是综合了性能和数据安全性方面考虑,可重复读是一个适用于大多数场景的情况。
4. 如何切换事务隔离级别?
在MySQL中,可以使用以下语句来切换事务隔离级别:
1. 查看当前的事务隔离级别:
SELECT @@tx_isolation;
2. 切换事务隔离级别:
SET SESSION TRANSACTION ISOLATION LEVEL <隔离级别>;
其中,<隔离级别>可以是以下几种之一:
READ UNCOMMITTED:读未提交
READ COMMITTED:读已提交
REPEATABLE READ:可重复读
SERIALIZABLE:串行化
例如,要将事务隔离级别切换为可重复读:
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
3. 验证事务隔离级别是否已切换:
SELECT @@tx_isolation;
需要注意的是,以上语句只会对当前会话生效,如果需要对全局生效,可以使用下面语句:
SET GLOBAL TRANSACTION ISOLATION LEVEL <隔离级别>
但是,一般情况下不建议修改全局的事务隔离级别,因为可能会对其他会话产生影响。
5. 哪些业务场景下要使用数据库事务?
以下是一些生活常见的场景,可能需要使用事务:
实在太多了,根据项目说就可以了,这里随便扯两个常见的。
银行转账:当一个用户从一个账户向另一个账户转账时,需要确保资金的安全和一致性。使用事务可以保证在转账过程中,资金从一个账户减少,同时另一个账户增加,如果其中一个操作失败,整个转账过程将被回滚。
在线支付:当用户下单并支付时,需要确保订单的支付和库存的减少是原子操作。使用事务可以保证在支付过程中,订单状态更新为已支付,同时库存减少,如果其中一个操作失败,整个支付过程将被回滚。
这两个场景都涉及到多个操作的原子性和一致性,使用事务可以确保这些操作要么全部成功,要么全部失败。