前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >转账会不会出现钱扣了对方也没收到钱的情况?

转账会不会出现钱扣了对方也没收到钱的情况?

作者头像
数据库交流
发布2022-04-25 09:13:42
发布2022-04-25 09:13:42
35800
代码可运行
举报
文章被收录于专栏:悦专栏悦专栏
运行总次数:0
代码可运行

今天大年初五迎财神,那么提到“财”,我们是否考虑过一个问题:转账会不会出现钱扣了对方也没收到钱的情况?首先财神不同意,另外按照现在的技术,基本也不会出现,因为目前一个转账操作基本在一个事务中。事务内的语句,要么全部执行成功,要么全部执行失败。也就是说,上面转账过程中,即使中间出现问题,也会回滚,取消扣钱操作。

那 MySQL 事务还有哪些特性呢?这一节内容就来聊聊。

1 事务控制

开始一个事务

代码语言:javascript
代码运行次数:0
运行
复制
begin;

或者

代码语言:javascript
代码运行次数:0
运行
复制
start transaction;

提交事务:

代码语言:javascript
代码运行次数:0
运行
复制
commit;

回滚事务

代码语言:javascript
代码运行次数:0
运行
复制
rollback;

参数 autocommit 可以控制当前会话是否自动提交,如果值为 1,则表示自动提交,每次执行事务不需要我们执行 begin 或者 start transaction。

如果全局为自动提交,但是想要部分 SQL 禁用自动提交,则使用下面的方法:

代码语言:javascript
代码运行次数:0
运行
复制
start transaction;
update table1 set a=1 where id=1;
update table2 set a=2 where id=1;
commit;

2 ACID 特性

一个运行良好的事务处理系统,必须具备 ACID 特性:

  • A: atomicity(原子性) :要么全执行,要么全都不执行
  • C: consistency(一致性):在事务开始和完成时,数据都必须保持一致状态
  • I: isolation(隔离性) :事务处理过程中的中间状态对外部是不可见的。
  • D: durability(持久性) :事务完成之后,它对于数据的修改是永久性的。

至于 MySQL 是如何来保证这些特性,我们在后面的文章详细介绍。

3 事务隔离级别

MySQL 有四种隔离级别:

  • READ UNCOMMITTED(读未提交,RU):在该隔离级别,所有事务都可以看到其它未提交的事务的执行结果。可能会出现脏读。
  • READ COMMITTED(读已提交,RC):一个事务只能看见已经提交事务所做的改变。因为同一事务的其它实例在该实例处理期间可能会有新的 commit,所以可能出现幻读。
  • REPEATABLE READ(可重复读,RR):这是 MySQL 的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行。消除了脏读、不可重复读,默认也不会出现幻读。
  • SERIALIZABLE(串行):这是最高的隔离级别,它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。一般不建议使用。

如何选择合适的隔离级别:

  • 对于 RU 隔离级别,会导致脏读,因此生产环境不建议使用。
  • 对于 RC 隔离级别,相比 RU 隔离级别,不会出现脏读;但是会出现幻读,一个事务中的两次执行同样的查询,可能得到不一样的结果。
  • 对于 RR 隔离级别,相比 RC 隔离级别,解决了部分幻读,但是相对于 RC,锁的范围可能更大了。
  • 对于 Serializable 隔离级别,因为它强制事务串行执行,会在读取的每一行数据上都加锁,因此可能会导致大量的超时和锁争用的问题。生成环境不建议使用。
  • 生产环境一般选择 RC 或者 RR。

4 有关 RC 和 RR 的对比实验

执行下面 SQL,进行实验前准备:

代码语言:javascript
代码运行次数:0
运行
复制
use martin;

drop procedure if exists insert_t1; 
delimiter ;;
create procedure insert_t1() 
begin

drop table if exists t1;

CREATE TABLE `t1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_c` (`a`)
) ENGINE=InnoDB CHARSET=utf8mb4;
insert into t1(a,b) values (1,1),(2,2);

end;;
delimiter ;

4.1 Read Committed 实验

执行初始化语句:

代码语言:javascript
代码运行次数:0
运行
复制
call insert_t1();

进行实验:

session1

session2

set session transaction_isolation='READ-COMMITTED';

set session transaction_isolation='READ-COMMITTED';

begin;

begin;

select * from t1 where a=1;

insert into t1(a,b) values (1,3);

select * from t1 where a=1;

commit;

select * from t1 where a=1;

commit;

session2 写入了新数据未提交的情况下,session1 无法查看到新记录,等到 session2 提交之后,session1 才能看到 session2 写入的数据。出现了一个事务中的两次执行同样的查询,得到不一样的结果,也就是幻读。

4.2 Repeatable Read 实验

执行初始化语句:

代码语言:javascript
代码运行次数:0
运行
复制
call insert_t1();

进行实验:

session1

session2

set session transaction_isolation='REPEATABLE-READ';

set session transaction_isolation='REPEATABLE-READ';

begin;

begin;

select * from t1 where a=1;

insert into t1(a,b) values (1,3);

select * from t1 where a=1;

commit;

select * from t1 where a=1;

commit;

select * from t1 where a=1;

session2 写入了新数据未提交的情况下,session1 无法查看到新记录,等到 session2 提交但是 session1 还未提交时,session1 还是不能看到新记录,没有出现 RC 隔离级别实验的幻读现象。需要等 session1 事务提交之后,才能查看到 session2 写入的新数据。

今天的内容就到这里,《MySQL 基础知识笔记》系列文章持续更新中

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2022-02-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 悦专栏 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 事务控制
  • 2 ACID 特性
  • 3 事务隔离级别
  • 4 有关 RC 和 RR 的对比实验
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档