事务transaction

什么是事务
事务的英文是transaction,事务可以保证多个操作原子性,对于数据库来说,事务可以保证批量的DML要么全成功,要么全失败。通常一个事务对应一个完整的业务,例如银行转账。比如银行账户表t_bank:

在这里插入图片描述

1001的账户向1002的账户进行转账500元的操作,此时将会执行两条SQL语句:

update t_bank set money=500 where account=1001;
update t_bank set money=2500 where account=1002;

如果上面的sql语句第一条执行成功了,但是由于某些原因第二条sql语句执行失败了,此时账户1001上的金额变成了500,而账户1002上的金额是2000,这样就不正确了。
为了能够正常的执行业务,上面两条sql语句要么全部执行成功,要么全部执行失败,因为他们是最小的业务单元,不能再进行拆分了。
当第一条sql语句执行结束后,并不会立即修改数据库表中的数据,而是在内存中记录一下,第二条sql语句执行成功后,才会修改数据库表中的数据,如果第二条sql语句执行失败了,则将清空内存中的记录,此时并不会修改数据库表中的数据,要实现这样的功能,就必须使用事务来完成。

事务具有四个特征ACID

  • 原子性(Atomicity),事务是最小单元,不可再分;
  • 一致性(Consistency),事务要求所有的DML语句操作的时候,必须保证同时成功或同时失败;
  • 隔离性(Isolation),一个事务不会影响其他事务的执行;
  • 持久性(Durability),在事务完成之后,该事务对数据库所作的更改将持久地保存在数据库中,并不会被回滚;

MySQL事务的提交和回滚
MySQL中默认情况下,事务是自动提交的,当执行一条DML语句时,就开启并且自动提交了事务。可以通过下面的语句查看事务是否是自动提交的:

show variables like '%commit%';

如果想要关闭MySQL事务的自动提交,可以使用下面语句手动开启事务:

start transaction;

为了方便演示提交和回滚,先初始化一些数据:

create table t_bank(
    account int(10) primary key,
    money int(15)
);

insert into t_bank values 
(1001,1000),
(1002,2000);

手动开启事务:

start transaction;

执行下面语句:

update t_bank set money=500 where account=1001;
update t_bank set money=2500 where account=1002;

执行查询操作:

select * from t_bank;

数据已改变。

在这里插入图片描述

重新开启一个MySQL连接,执行查询操作:

select * from t_bank;

因为是新开启的MySQL连接,所以查询结果中money字段的数据并未改变,说明上面的操作还没有修改数据库中的字段值。

在这里插入图片描述

回到之前的连接中,输入:

rollback;

此时事务将会回滚,清空内存中的记录,不会修改数据库中的字段值。

再次执行查询操作:

select * from t_bank;

数据并未改变。

上面输入

rollback;

命令,数据库会执行回滚操作,如果想要提交事务,则输入命令:

commit;

事务的隔离级别

  • read uncommitted 读未提交
    事务A和事务B,事务A未提交的数据,事务B可以读取,这里读取到的数据叫做“脏数据”,该级别最低,一般只是理论上存在,数据库的默认隔离级别都高于该级别。
  • read committed 读已提交
    事务A和事务B,事务A提交的数据,事务B才可读取到,换句话说:对方事务提交之后的数据,当前事务才可读取到,可以避免读取“脏数据”,但是改级别会有“不可重复读”的问题,事务B读取一条数据,当事务A修改这条数据并提交后,事务B再读取这条数据时,数据发生了变化,即事务B每次读取的数据有可能不一致,这种情况叫做“不可重复读”。
  • repeatable read 重复读
    MySQL默认的隔离级别是重复读,该级别可以达到“重复读”的效果,但是会有“幻读”的问题,即事务A读取数据,此时事务B修改了这条数据,但是事务A读取的还是之前的旧数据的内容,这样就出现了幻读。
  • serializable 串行化
    事务A和事务B,事务A在操作数据库表中数据的时候,事务B只能排队等待,这样保证了同一个时间点上只有一个事务操作数据库,该级别可以解决“幻读”的问题。但是这种级别一般很少使用,因为吞吐量太低,用户体验不好。

在这里插入图片描述

查看当前会话的隔离级别:

select @@tx_isolation;

修改隔离级别:

set global transaction isolation level 隔离级别
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
nestjs是一个基于Node.js的开发框架,而是nestjs中常用的一个数据库ORM工具。在nestjs中使用typeorm进行事务回滚可以通过以下步实现: 1. 首先,你需要在nestjs项目中安装typeorm和数据库驱动程序(如mysql、等)的相关依赖。 2. 在中,你可以使用装饰器`@()`来标记一个方法需要在事务中执行。这个装饰器可以应用在controller或service层方法上。 3. 在需要回滚事的方法中,你可以使用typeorm提供的`EntityManager`来管理事务。通过调用`entityManager.transaction()`方法,你可以创建一个新的事务。 4. 在事务中执行数据库操作时,如果发生错误或者需要回滚事务,你可以使用`entityManager.rollback()`方法来回滚事务。 5. 如果所有的数据库操作都成功完成,你可以使用`entityManager.commit()`方法来提交事务。 下面是一个nestjs中使用typeorm进行事务回滚的示例代码: ```typescript import { Injectable } from '@nestjs/common'; import { InjectEntityManager } from '@nestjs/typeorm'; import { EntityManager } from 'typeorm'; @Injectable() export class MyService { constructor( @InjectEntityManager() private readonly entityManager: EntityManager, ) {} @Transaction() async myMethod(): Promise<void> { try { await this.entityManager.transaction(async (entityManager) => { // 在事务中执行数据库操作 await entityManager.query('INSERT INTO table1 (column1) VALUES (value1)'); await entityManager.query('INSERT INTO table2 (column2) VALUES (value2)'); }); } catch (error) { // 发生错误时回滚事务 await this.entityManager.rollback(); throw error; } } } ``` 在上面的示例中,`myMethod()`方法被标记为`@Transaction()`,表示该方法需要在事务中执行。在事务中,我们使用`entityManager.query()`方法执行数据库操作。如果发生错误,我们会回滚事务并抛出错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值