mysql事务两个表加锁顺序_MySQL事务与锁详解

文章目标1、 掌握事务的特性与事务并发造成的问题2、事务一致性问题解决方案3、MVCC的原理4、锁的分类、行锁的原理、行锁的算法1 什么是数据库的事务?1.1 事务的典型场景在项目里面,什么地方会开启事务,或者配置了事务?无论是在方法上加注解,还 是配置切面比如下单,会操作订单表,资金表,物流表等等,这个时候我们需要让这些操作都 在一个事务里面完成。当一个业务流程涉及多个表的操作的时候,我们希望它...
摘要由CSDN通过智能技术生成

文章目标

1、 掌握事务的特性与事务并发造成的问题

2、事务一致性问题解决方案

3、MVCC的原理

4、锁的分类、行锁的原理、行锁的算法

1 什么是数据库的事务?

1.1 事务的典型场景

在项目里面,什么地方会开启事务,或者配置了事务?无论是在方法上加注解,还 是配置切面

比如下单,会操作订单表,资金表,物流表等等,这个时候我们需要让这些操作都 在一个事务里面完成。当一个业务流程涉及多个表的操作的时候,我们希望它们要么是全部成功的,要么都不成功,这个时候我们会启用事务。

1.2 事务的定义

什么是事务:事务是数据库管理系统(DBMS)执行过程中的一个逻辑单元,由一个有限的数据库操作序列构成。

这里面有两个关键点:第一个,它是数据库最小的工作单元,是不可以再分的。第 二个,它可能包含了一个或者一系列的 DML 语句,包括 insert delete update。

(单条 DDL(create drop)和 DCL(grant revoke)也会有事务)

1.3 那些存储引擎支持事务

InnoDB 支持事务,这个也是它成为默认的存储引擎 的一个重要原因,另一个是NDB。

1.4 事务的四大特性

事务的四大特性:ACID。

第一个,原子性,Atomicity,也就是我们刚才说的不可再分,也就意味着我们对数 据库的一系列的操作,要么都是成功,要么都是失败,不可能出现部分成功或者部分失败的情况。以转账的场景为例,一个账户的余额减少,对应一个账户的增加,这两个一 定是同时成功或者同时失败的。

全部成功比较简单,问题是如果前面一个操作已经成功了,后面的操作失败了,怎 么让它全部失败呢?这个时候我们必须要回滚。 原子性,在 InnoDB 里面是通过 undo log 来实现的,它记录了数据修改之前的值(逻 辑日志),一旦发生异常,就可以用 undo log 来实现回滚操作。

第二个,一致性,consistent,指的是数据库的完整性约束没有被破坏,事务执行的前后都是合法的数据状态。比如主键必须是唯一的,字段长度符合要求。

除了数据库自身的完整性约束,还有一个是用户自定义的完整性

比如说转账的这个场景,A 账户余额减少 1000,B 账户余额只增加了 500,这个时 候因为两个操作都成功了,按照我们对原子性的定义,它是满足原子性的, 但是它没有 满足一致性,因为它导致了会计科目的不平衡。 还有一种情况,A 账户余额为 0,如果这个时候转账成功了,A 账户的余额会变成 -1000,虽然它满足了原子性的,但是我们知道,借记卡的余额是不能够小于 0 的,所以 也违反了一致性。用户自定义的完整性通常要在代码中控制

第三个,隔离性,Isolation,我们有了事务的定义以后,在数据库里面会有很多的 事务同时去操作我们的同一张表或者同一行数据,必然会产生一些并发或者干扰的操作, 那么我们对隔离性的定义,就是这些很多个的事务,对表或者行的并发操作,应该是透明的,互相不干扰的。通过这种方式,我们最终也是保证业务数据的一致性。

最后一个叫做持久性,Durable,事务的持久性是什么意思呢?我们对数据库的任意 的操作,增删改,只要事务提交成功,那么结果就是永久性的,不可能因为我们系统宕 机或者重启了数据库的服务器,它又恢复到原来的状态了。这个就是事务的持久性。

持久性怎么实现呢?数据库崩溃恢复(crash-safe)是通过什么实现的?

持久性是通过 redo log 和 double write 双写缓冲来实现的,我们操作数据的时候,

会先写到内存的 buffer pool 里面,同时记录 redo log,如果在刷盘之前出现异常,在重启后就可以读取 redo log 的内容,写入到磁盘,保证数据的持久性。

当然,恢复成功的前提是数据页本身没有被破坏,是完整的,这个通过双写缓冲 (double write)保证。

原子性,隔离性,持久性,最后都是为了实现一致性。

1.5 数据库什么时候出现事务

无论是我们在 Navicat 的这种工具里面去操作,还是在我们的 Java 代码里面通过API 去操作,还是加上@Transactional 的注解或者 AOP 配置,其实最终都是发送一个指令到数据库去执行,Java 的 JDBC 只不过是把这些命令封装起来了。

执行这样一条更新语句的时候,它有事务吗?

update student set sname = 'xxx' where id=1;

实际上,它自动开启了一个事务,并且提交了,所以最终写入了磁盘。

这个是开启事务的第一种方式,自动开启和自动提交。

InnoDB 里面有一个 autocommit 的参数(分成两个级别, session 级别和 global 级别)。

show variables like 'autocommit';

它的默认值是 ON。autocommit 这个参数是什么意思呢?是否自动提交。如果它的值是 true/on 的话,我们在操作数据的时候,会自动开启一个事务,和自动提交事务。 否则,如果我们把 autocommit 设置成 false/off,那么数据库的事务就需要我们手动地去开启和手动地去结束。

手动开启事务也有几种方式,一种是用 begin;一种是用 start transaction。

那么怎么结束一个事务呢?我们结束也有两种方式,第一种就是提交一个事务, commit;还有一种就是 rollback,回滚的时候,事务也会结束。还有一种情况,客户端 的连接断开的时候,事务也会结束。

1.6 事务并发会带来什么问题?

当很多事务并发地去操作数据库的表或者行的时候,如果没有我们刚才讲的事务的 Isolation 隔离性的时候,会带来哪些问题呢?

一、我们有两个事务,一个是 Transaction A,一个是 Transaction B,在第一个事务里 面,它首先通过一个 where id=1 的条件查询一条数据,返回 name=Ada,age=16 的这条数据。然后第二个事务,它同样地是去操作 id=1 的这行数据,它通过一个 update 的语句,把这行 id=1 的数据的 age 改成了 18,但是注意,它没有提

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值