mysql事务

what

MYSQL事务主要用于保证一串事情要么都成功,要么就回滚,例如付款后,要先写入支付订单表,再个人信息中加入会员权益。这两个操作要么顺序执行成功,要么就回滚

原则

ACID

  • Atomicity原子性

    确保事务内的所有操作都成功完成,否则事务将被中止在故障点,以前的操作将回滚到以前的状态。

  • Consistency一致性

    数据库的修改是一致的

  • Isolation隔离性

    事务是彼此独立的

  • Durability可靠性

    确保事务提交后,结果永久存在

隔离性

隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括

读未提交(Read uncommitted)–不严格

读提交(read committed)

可重复读(repeatable read)–默认级别(避免幻读)

串行化(Serializable)–最严格

没有隔离性的问题

1.脏读

1
2
update account set money=money+100 where name=’B’;
update account set money=money - 100 where name=’A’;

当执行第一条语句的时候,事务没有提交,那么来读B的账户钱都多了100块

脏读:读取了另一个事务未提交的数据

2.不可重复读

情景:多次读同一个数据的时候,这个数据被别人改了,导致结果不一致

3.幻读

幻读和不可重复读一样,读取到了另外一条已经提交的事务,所不同的是它针对的是一批数据的整体

实现方式

自动方式

beginTransactionScope(scope, ctx)

1
2
3
4
5
6
7
const result = await app.mysql.beginTransactionScope(async conn => {
// don't commit or rollback by yourself
await conn.insert(table, row1);
await conn.update(table, row2);
return { success: true };
}, ctx);
// if error throw on scope, will auto rollback

手动方式

beginTransaction

1
2
3
4
5
6
7
8
9
10
const conn = await app.mysql.beginTransaction(); // 初始化事务
try {
await conn.insert(table, row1); // 第一步操作
await conn.update(table, row2); // 第二步操作
await conn.commit(); // 提交事务
} catch (err) {
// error, rollback
await conn.rollback(); // 一定记得捕获异常后回滚事务!!
throw err;
}

表达式Literal

app.mysql.literals.now

查看数据库事务隔离性级别

1
select @@tx_isolation;