MySQL 事务

MySQL 事务主要⽤于处理操作量⼤,复杂度⾼的数据。⽐如说,在⼈员管理系统中,你删除⼀个⼈员,你即需要删除⼈员的基本资料,也要删除和该⼈员相关的信息,如信箱,⽂章等等,这样,这些数据库操作语句就构成⼀个事务。

ACID — 事务基本要素:
事务是由⼀组SQL语句组成的逻辑处理单元,具有4个属性,通常简称为事务的ACID属性。
A (Atomicity) 原⼦性:整个事务中的所有操作,要么全部完成,要么全部不完成,不可能停滞在中间某个环节。事务在执⾏过程中发⽣错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执⾏过⼀样。
C (Consistency) ⼀致性:在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
I (Isolation)隔离性:⼀个事务的执⾏不能其它事务⼲扰。即⼀个事务内部的操作及使⽤的数据对其它并发事务是隔离的,并发执⾏的各个事务之间不能互相⼲扰。
D (Durability) 持久性:在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中并不会被回滚。

并发事务处理带来的问题:
更新丢失(Lost Update):事务A和事务B选择同⼀⾏,然后基于最初选定的值更新该⾏时,由于两个事务都不知道彼此的存在,就会发⽣丢失更新问题
脏读(Dirty Reads):事务A读取了事务B更新的数据,然后B回滚操作,那么A读取到的数据是脏数据
不可重复读(Non-Repeatable Reads):事务 A 多次读取同⼀数据,事务B在事务A多次读取的过程中,对数据作了更新并提交,导致事务A多次读取同⼀数据时,结果不⼀致。
幻读(Phantom Reads):幻读与不可重复读类似。它发⽣在⼀个事务A读取了⼏⾏数据,接着另⼀个并发事务B插⼊了⼀些数据时。在随后的查询中,事务A就会发现多了⼀些原本不存在的记录,就好像发⽣了幻觉⼀样,所以称为幻读。
幻读和不可重复读的区别: 不可重复读的重点是修改:在同⼀事务中,同样的条件,第⼀次读的数据和第⼆次读的数据不⼀样。(因为中间有其他事务提交了修改)
幻读的重点在于新增或者删除:在同⼀事务中,同样的条件,,第⼀次和第⼆次读出来的记录数不⼀样。(因为中间有其他事务提交了插⼊/删除)

并发事务处理带来的问题的解决办法:
“更新丢失”通常是应该完全避免的。但防⽌更新丢失,并不能单靠数据库事务控制器来解决,需要应⽤程序对要更新的数据加必要的锁来解决,因此,防⽌更新丢失应该是应⽤的责任。
“脏读” 、 “不可重复读”和“幻读” ,其实都是数据库读⼀致性问题,必须由数据库提供⼀定的事务隔离机制来解决:
⼀种是加锁:在读取数据前,对其加锁,阻⽌其他事务对数据进⾏修改。
另⼀种是数据多版本并发控制(MultiVersion Concurrency Control,简称 MVCC或 MCC),也称为多版本数据库:不⽤加任何锁, 通过⼀定机制⽣成⼀个数据请求时间点的⼀致性数据快照 (Snapshot), 并⽤这个快照来提供⼀定级别 (语句级或事务级) 的⼀致性读取。从⽤户的⻆度来看,好象是数据库可以提供同⼀数据的多个版本。

事务隔离级别
数据库事务的隔离级别有4种,由低到⾼分别为
READ-UNCOMMITTED(读未提交):最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读。
READ-COMMITTED(读已提交):允许读取并发事务已经提交的数据,可以阻⽌脏读,但是幻读或不可重复读仍有可能发⽣。
REPEATABLE-READ(可重复读):对同⼀字段的多次读取结果都是⼀致的,除⾮数据是被本身事务⾃⼰所修改,可以阻⽌脏读和不可重复读,但幻读仍有可能发⽣。
SERIALIZABLE(可串⾏化):最⾼的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执⾏,这样事务之间就完全不可能产⽣⼲扰,也就是说,该级别可以防⽌脏读、不可重复读以及幻读。
查看当前数据库的事务隔离级别:

show variables like 'tx_isolation';

数据库的事务隔离越严格,并发副作⽤越⼩,但付出的代价就越⼤,因为事务隔离实质上就是使事务在⼀定程度上“串⾏化”进⾏,这显然与“并发”是⽭盾的。同时,不同的应⽤对读⼀致性和事务隔离程度的要求也是不同的,⽐如许多应⽤对“不可重复读”和“幻读”并不敏感,可能更关⼼数据并发访问的能⼒。

MySQL InnoDB 存储引擎的默认⽀持的隔离级别是 REPEATABLE-READ(可重读)。可以通过SELECT@@tx_isolation;命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;
这⾥需要注意的是:与SQL标准不同的地⽅在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使⽤的是Next-Key Lock 算法,因此可以避免幻读的产⽣,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认⽀持的隔离级别是 REPEATABLE-READ(可重读)已经可以完全保证事务的隔离性要求,即达到了 SQL标准的 SERIALIZABLE(可串⾏化)隔离级别,⽽且保留了⽐较好的并发性能。因为隔离级别越低,事务请求的锁越少,所以⼤部分数据库系统的隔离级别都是READ-COMMITTED(读已提交):,但是InnoDB 存储引擎默认使⽤ REPEATABLE-READ(可重读)并不会有任何性能损失。

MVCC 多版本并发控制
MySQL的⼤多数事务型存储引擎实现都不是简单的⾏级锁。基于提升并发性考虑,⼀般都同时实现了多版本并发控制(MVCC),包括Oracle、PostgreSQL。只是实现机制各不相同。
可以认为 MVCC 是⾏级锁的⼀个变种,但它在很多情况下避免了加锁操作,因此开销更低。虽然实现机制有所不同,但⼤都实现了⾮阻塞的读操作,写操作也只是锁定必要的⾏。
MVCC 的实现是通过保存数据在某个时间点的快照来实现的。也就是说不管需要执⾏多⻓时间,每个事物看到的数据都是⼀致的。典型的MVCC实现⽅式,分为乐观(optimistic)并发控制和悲观(pressimistic)并发控制。下边通过InnoDB的简化版⾏为来说明 MVCC 是如何⼯作的。
InnoDB 的 MVCC,是通过在每⾏记录后⾯保存两个隐藏的列来实现。这两个列,⼀个保存了⾏的创建时间,⼀个保存⾏的过期时间(删除时间)。当然存储的并不是真实的时间,⽽是系统版本号(system version number)。每开始⼀个新的事务,系统版本号都会⾃动递增。事务开始时刻的系统版本号会作为事务的版本号,⽤来和查询到的每⾏记录的版本号进⾏⽐较。 MVCC 只在 COMMITTED READ(读提交)和REPEATABLE READ(可重复读)两种隔离级别下⼯作。

事务的实现
事务的实现是基于数据库的存储引擎。不同的存储引擎对事务的⽀持程度不⼀样。MySQL 中⽀持事务的存储引擎有 InnoDB 和 NDB。事务的实现就是如何实现ACID特性。
事务的隔离性是通过锁实现,⽽事务的原⼦性、⼀致性和持久性则是通过事务⽇志实现。
事务⽇志包括:重做⽇志redo和回滚⽇志undo redo log 实现持久化和原⼦性。

在innoDB的存储引擎中,事务⽇志通过重做(redo)⽇志和innoDB存储引擎的⽇志缓冲(InnoDB Log Buffer)实现。事务开启时,事务中的操作,都会先写⼊存储引擎的⽇志缓冲中,在事务提交之前,这些缓冲的⽇志都需要提前刷新到磁盘上持久化,这就是DBA们⼝中常说的“⽇志先⾏”(Write-AheadLogging)。当事务提交之后,在Buffer Pool中映射的数据⽂件才会慢慢刷新到磁盘。此时如果数据库崩溃或者宕机,那么当系统重启进⾏恢复时,就可以根据redo log中记录的⽇志,把数据库恢复到崩溃前的⼀个状态。未完成的事务,可以继续提交,也可以选择回滚,这基于恢复的策略⽽定。
在系统启动的时候,就已经为redo log分配了⼀块连续的存储空间,以顺序追加的⽅式记录Redo Log,通过顺序IO来改善性能。所有的事务共享redo log的存储空间,它们的Redo Log按语句的执⾏顺序,依次交替的记录在⼀起。

undo log(回滚⽇志) 实现⼀致性
undo log 主要为事务的回滚服务。在事务执⾏的过程中,除了记录redo log,还会记录⼀定量的undo log。undo log记录了数据在每个操作前的状态,如果事务执⾏过程中需要回滚,就可以根据undo log进⾏回滚操作。单个事务的回滚,只会回滚当前事务做的操作,并不会影响到其他的事务做的操作。
Undo记录的是已部分完成并且写⼊硬盘的未完成的事务,默认情况下回滚⽇志是记录下表空间中的(共享表空间或者独享表空间)⼆种⽇志均可以视为⼀种恢复操作,redo_log是恢复提交事务修改的⻚操作,⽽undo_log是回滚⾏记录到特定版本。⼆者记录的内容也不同,redo_log是物理⽇志,记录⻚的物理修改操作,⽽undo_log是逻辑⽇志,根据每⾏记录进⾏记录。

MySQL 有多少种⽇志?
错误⽇志:记录出错信息,也记录⼀些警告信息或者正确的信息。
查询⽇志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执⾏。
慢查询⽇志:设置⼀个阈值,将运⾏时间超过该值的所有SQL语句都记录到慢查询的⽇志⽂件中。
⼆进制⽇志:记录对数据库执⾏更改的所有操作。
中继⽇志:中继⽇志也是⼆进制⽇志,⽤来给slave 库恢复
事务⽇志:重做⽇志redo和回滚⽇志undo

  • 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、付费专栏及课程。

余额充值