MySQL事务

1、四大特性

事务是一个最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务是一个最小的工作单元);一个完整的业务需要批量的DML(insert、update、delete)语句共同联合完成;事务只和DML语句有关,或者说DML语句才有事务。这个和业务逻辑有关,业务逻辑不同,DML语句的个数不同。

1.1、原子性(Atomicity)

一个事务包含多个操作,原子性就是这些批量操作要么全部执行,要么全都不执行。实现事务原子性,就要支持回滚操作,在某个操作失败后,回滚到事务执行之前的状态。

1.1.1、例子

某账户A要转给账户B一笔钱(1000元),需要完成如下操作1(A账户减1000元)、操作2(B账户加1000元),原子性就是要么批量操作全部成功执行提交(COMMIT)数据状态为最终状态,要么批量操作部分失败执行回滚(ROLLBACK)数据状态到开始的时候。

在这里插入图片描述

1.1.2、实现原理

如果事务过程种出现了异常,需要回滚数据,这时就用到undo log保证原子性。一般来说,通常进行insert/delete/update操作时会产生一条undo log,但是update更新主键操作时会产生两条undo log(即,根据主键软删除的undo log和插入新主键记录的undo log)。
在这里插入图片描述

1.2、一致性(Consistency)

数据库处理前后结果应与其所抽象的客观世界中真实状况保持一致。这种一致性是一种需要管理员去定义的规则。管理员如何指定规则,数据库就严格按照这种规则去处理数据。

1.2.1、例子

某用户A要转给用户B一笔钱(1000元),需要用户A钱包少1000元钱,用户B钱包多1000元钱,同时,银行数据库中账户A减1000元,账户B加1000元。
在这里插入图片描述

1.2.2、实现原理

通过undo log、redo log、隔离性、算法共同实现。

1.3、隔离性(Isolation)

数据库允许多个并发事务同时对某条数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。

1.3.1、并发场景

事务A事务B备注
场景1不存在并发冲突
场景2存在并发冲突。(如:脏读、幻读、不可重复读)
场景3存在并发冲突。(如:脏读、幻读、不可重复读)
场景4存在并发冲突。(如:更新丢失等)

1.3.2、隔离级别

1.3.2.1、读未提交(Read UnCommitted)

某个事务读到了另外一个事务未提交的修改过的记录(Record)。可能出现“脏读”、“不可重复读”、“幻读”的并发冲突。
在这里插入图片描述

1.3.2.2、读已提交(Read Committed)

某个事务读到了另外一个事务已提交的修改过的记录(Record)。可能出现“不可重复读”、“幻读”的并发冲突。
在这里插入图片描述

1.3.2.3、可重复读(Repeatable Read)

不管其它事务是否已经提交记录(Record),某个事务多次读取到该记录(Record)的结果一致。可能出现“幻读”的并发冲突。MVCC在一定程度可以避免幻读,但是不能完全解决幻读。
在这里插入图片描述

1.3.2.4、串行化(Serializable)

串行化指并行事务执行结果和串行执行结果保证一致。
在这里插入图片描述

1.3.3、实现原理

隔离性是通过“当前读”“快照读”共同实现。

1.3.3.1、当前读

当前读是一种悲观锁的读操作,它会对当前读取的数据进行加锁,所以读到的数据都是最新版本数据。主要包括以下几种操作:

select …… lock in share mode --(共享锁/共享读锁)
select …… for update --(排他锁/写锁)
update …… -- (排他锁)
insert …… --(排他锁)
delete …… --(排他锁)
1.3.3.2、快照读

快照读是一种不加锁的读操作,是InnoDB并发如此之高的核心原因之一。快照读在读写时不用加锁,不过可能会读到历史版本数据,简单的 SELECT 都属于快照读,MySQL的快照读是基于MVCC(多版本并发控制)来实现的。MVCC是基于undo log、版本链、ReadView实现。
在这里插入图片描述
在mysql存储的版本链数据中,除了我们显式定义的字段,mysql会隐含的帮我们定义几个字段。

  • trx_id:事务id,每进行一次事务操作,就会自增1。
  • roll_pointer:回滚指针,用于找到上一个版本的数据,结合undo log进行回滚。
ReadView-字段备注
m_ids还未commit的活跃事务ID
min_trx_idm_ids的最小事务ID
max_trx_id将要分配的下一个事务ID
creator_trx_id创建当前ReadView的事务ID

当我们用SELECT读取数据时,这一时刻的数据会有很多个版本(如,图 6),但我们并不知道读取哪个版本,这时就靠ReadView数据结构来对读取版本进行限制,通过“ReadView+规则”就能够知道读取哪个版本。当事务级别为“读已提交”,那么每个SELECT快照读都会生成并获取最新的ReadView,所以每次的查询结果都不一样的。当事务级别为“可重复读”,那么只有在同一个事务第一个SELECT快照读才会创建ReadView,之后的每次快照读都使用的同一个ReadView,所以每次的查询结果都是一样的。

1.4、持久性(Durability)

事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。

1.4.1、实现原理

如果事务已经提交,数据未刷入磁盘,服务器宕机,这时就用到redo log保证持久性。服务器在重启的时候,可以读取redo logo中的数据,对数据进行恢复。
在这里插入图片描述

2、总结

2.1、四大特性如何实现的

  • 原子性:通过undo log实现。
  • 持久性:通过redo log实现。
  • 隔离性:通过“当前读”(核心技术:悲观锁)“快照读”(核心技术:MVCC)共同实现。
  • 一致性:通过undo logredo log隔离性算法共同实现。

2.2、事务的开始时间点

一般我们会认为BEGINE/START TRANSACTION是事务开始的时间点,也就是一旦我们执行了START TRANSACTION,就认为事务已经开始了,其实这是错误的。事务开始的真正的时间点(LSN)是START TRANSACTION之后执行的第一条语句,不管是什么语句、成功与否;如果想要达到将START TRANSACTION作为事务开始的时间点,那么我们必须使用START TRANSACTION WITH CONSISTNET SNAPSHOT,它的含义是执行START TRANSACTION的同时建立本事务一致性读的SNAPSHOT,而不是等到执行第一条语句时,才开始事务,并且建立一致性读的SNAPSHOT,效果等价于START TRANSACTION之后,马上执行一条SELECT语句。

2.3、隔离级别与并发冲突关系

由于隔离级别中的“读未提交”不加锁限制,“串行化”相当于单线程执行,效率太差,所以,“读未提交”和“串行化”基本上是不需要考虑的隔离级别。

脏读不可重复读幻读
读未提交可能会可能会可能会
读已提交可能会可能会
可重复读可能会
串行化
  • 脏读:某一个时刻,某个事务读到了另外一个事务未提交修改过的记录(Record)。
  • 不可重复读:某两个时刻,某个事务分别读取的记录(Record)不一致。
  • 幻读:某两个时刻,某个事务分别读取的数量(Count)不一致,即数量变多或者变少。

2.4、MySQL的日志

日志类别说明备注
错误日志错误日志记录了当MySQL启动、停止或者服务器运行过程中发生任何严重错误时的相关信息,当数据库出现任何故障导致无法正常使用时,可以首先查看此日志。默认开启
二进制日志(binlog日志)记录了所有的DDLDML语句,但不包括数据查询语句,此日志对于灾难恢复时非常重要,并且MySQL的主从复制、增量恢复,也是通过该binlog 实现的。默认未开启,需要手动开启
查询日志它记录了客户端的所有操作语句,包括增删改查所有语句。默认未开启,需要手动开启,注意,高并发场景企业里普通查询日志一般是关闭的(默认也是关闭的),主要是因为IO性能问题;
慢查询日志它是用来记录查询效率较低的SQL语句的日志,慢查询日志记录所有执行时间超过参数long_query_time设置值,默认值为10s。默认未开启,需要手动开启
审计日志根据国家等保审计合规要求,数据库要开启审计功能,它主要记录用户登录,对数据库的操作管理,对数据库受到的风险行为进行告警,对攻击行为及时阻断,通过审计日志可以对用户访问数据库行为进行记录、分析和汇报,用来帮助用户事后生成合规报告、事故追根溯源,同时加强内外部数据库网络行为记录,提高数据资产安全。MySQL企业版有此功能,属于收费组件,此测试社会版使用第三方开源插件。
redo log重做日志,提供前滚操作,通常是物理日志,记录的是数据页的物理修改,而不是某一行或者某几行修改成怎样,它用来恢复到最后一次提交后物理数据页undo log不是redo log的逆向过程,他们都是用来恢复的日志;
undo log回滚日志,提供回滚操作,用来回滚到某个版本,undo log一般是逻辑日志,根据每行记录进行回滚。undo log不是redo log的逆向过程,他们都是用来恢复的日志;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MySQL 事务是指一组数据库操作,这些操作要么全部执行,要么全部不执行,其目的是保证在并发环境下,数据的一致性和完整性。MySQL 事务具有 ACID 性质,即原子性、一致性、隔离性和持久性。 MySQL 中使用事务需要使用 BEGIN、COMMIT 和 ROLLBACK 语句,其中 BEGIN 表示开启一个事务,COMMIT 表示提交事务,ROLLBACK 表示回滚事务事务的基本语法如下: ``` BEGIN; -- 执行一组数据库操作 COMMIT; -- 提交事务 -- 或者 ROLLBACK; -- 回滚事务 ``` 在 MySQL 中,事务的隔离级别分为四个等级,分别是 Read Uncommitted、Read Committed、Repeatable Read 和 Serializable。隔离级别越高,数据的一致性和完整性越高,但同时也会影响数据库的性能。 MySQL 事务的 ACID 性质有以下含义: 1. 原子性(Atomicity):事务中的所有操作要么全部执行成功,要么全部失败回滚,不会只执行其中的一部分操作。 2. 一致性(Consistency):事务执行前后,数据库中的数据必须保持一致性状态,即满足数据库的约束条件和完整性规则。 3. 隔离性(Isolation):事务之间应该是相互隔离的,一个事务的执行不应该被其他事务干扰,保证事务之间的数据相互独立。 4. 持久性(Durability):事务提交后,对数据库的修改应该是永久性的,即使出现系统故障或电源故障,也不应该对数据产生影响。 总之,MySQL 事务是一组数据库操作,具有 ACID 性质,可以通过 BEGIN、COMMIT 和 ROLLBACK 语句来实现,隔离级别越高,数据的一致性和完整性越高,但同时也会影响数据库的性能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值