MySQL-Transaktionen können auf folgende Weise gestartet werden:- 显式启动事务语句, begin 或 start transaction。配套的提交语句是 commit,或者回滚语句是 rollback。
# 更新学生名字
START TRANSACTION;
update student set name = '张三' where id = 2;
commit;
Nach dem Login kopieren
- set autocommit = 0,这个命令会将线程的自动提交关掉。意味着如果你只执行一个 select 语句,这个事务就启动了,而且并不会自动提交。这个事务持续存在直到你主动执行 commit 或 rollback 语句,或者断开连接。
- set autocommit = 1,表示 MySQL 自动开启和提交事务。 比如执行一个 update 语句,语句只完成后就自动提交了。不需要显示的使用 begin、commit 来开启和提交事务。所以当我们执行多个语句的时候,就需要手动的用 begin、commit 来开启和提交事务。
- start transaction with consistent snapshot;上面提到的 begin/start transaction 命令并不是一个事务的起点,在执行到它们之后的第一个操作 InnoDB 表的语句,事务才真正启动。如果你想要马上启动一个事务,可以使用 start transaction with consistent snapshot 命令。 第一种启动方式,一致性视图是在执行第一个快照读语句时创建的; 第二种启动方式,一致性视图是在执行 start transaction with consistent snapshot 时创建的。
02 事务隔离的实现
理解了隔离级别,那事务的隔离是怎么实现的呢?要想理解事务隔离,先得了解 MVCC 多版本的并发控制这个概念。而 MVCC 又依赖于 undo log 和 read view 实现。
2.1 什么是 MVCC?
百度上的解释是这样的:
MVCC,全称 Multi-Version Concurrency Control,即多版本并发控制。MVCC 是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问,在编程语言中实现事务内存。
MVCC 使得数据库读不会对数据加锁,普通的 SELECT 请求不会加锁,提高了数据库的并发处理能力;数据库写才会加锁。 借助 MVCC,数据库可以实现 READ COMMITTED,REPEATABLE READ 等隔离级别,用户可以查看当前数据的前一个或者前几个历史版本,保证了 ACID 中的 I 特性(隔离性)。
MVCC 只在 REPEATABLE READ 和 READ COMMITIED 两个隔离级别下工作。其他两个隔离级别都和 MVCC 不兼容 ,因为 READ UNCOMMITIED 总是读取最新的数据行,而不是符合当前事务版本的数据行。而 SERIALIZABLE 则会对所有读取的行都加锁。
2.1.1 InnDB 中的 MVCC
InnDB 中每个事务都有一个唯一的事务 ID,记为 transaction_id。它在事务开始时向 InnDB 申请,按照时间先后严格递增。
而每行数据其实都有多个版本,这就依赖 undo log 来实现了。每次事务更新数据就会生成一个新的数据版本,并把 transaction_id 记为 row trx_id。同时旧的数据版本会保留在 undo log 中,而且新的版本会记录旧版本的回滚指针,通过它直接拿到上一个版本。
所以,InnDB 中的 MVCC 其实是通过在每行记录后面保存两个隐藏的列来实现的。一列是事务 ID:trx_id;另一列是回滚指针:roll_pt。
2.2 undo log
回滚日志保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。
根据操作的不同,undo log 分为两种: insert undo log 和 update undo log。
2.2.1 insert undo log
insert 操作产生的 undo log,因为 insert 操作记录没有历史版本只对当前事务本身可见,对于其他事务此记录不可见,所以 insert undo log 可以在事务提交后直接删除而不需要进行 purge 操作。
purge 的主要任务是将数据库中已经 mark del 的数据删除,另外也会批量回收 undo pages
所以,插入数据时。它的初始状态是这样的:
2.2.2 update undo log
UPDATE 和 DELETE 操作产生的 Undo log 都属于同一类型:update_undo。(update 可以视为 insert 新数据到原位置,delete 旧数据,undo log 暂时保留旧数据)。
事务提交时放到 history list 上,没有事务要用到这些回滚日志,即系统中没有比这个回滚日志更早的版本时,purge 线程将进行最后的删除操作。
Eine Transaktion ändert die aktuellen Daten:
Eine andere Transaktion ändert die Daten:
Es gibt mehrere Versionen desselben Datensatzes in der Datenbank, bei der es sich um das erwähnte Multiversions-Parallelitätskontroll-MVCC handelt über .
Darüber hinaus können Sie das Rückgängig-Protokoll verwenden, um zum vorherigen Versionsstand zurückzukehren. Um beispielsweise zu V1 zurückzukehren, müssen Sie nur zwei Rollbacks nacheinander durchführen.
2.3 Leseansicht
Die Leseansicht ist eine konsistente Leseansicht, die von InnDB bei der Implementierung von MVCC verwendet wird, um die Implementierung der Isolationsstufen RC (Read Commit) und RR (Repeatable Read) zu unterstützen.
Die Leseansicht existiert nicht wirklich, sie ist nur ein Konzept und das Rückgängig-Protokoll ist ihre Verkörperung. Es wird hauptsächlich durch Version und Undolog berechnet. Seine Funktion besteht darin, zu bestimmen, welche Daten die Transaktion sehen kann.
Jede Transaktion oder Abrechnung verfügt über eine eigene Konsistenzansicht. Gewöhnliche Abfrageanweisungen sind konsistente Lesevorgänge, die die Sichtbarkeit der Datenversion basierend auf der Zeile trx_id und konsistenten Ansichten bestimmen.
2.3.1 Sichtbarkeitsregeln der Datenversion Die Leseansicht enthält hauptsächlich andere aktive Lese- und Schreibtransaktionen im aktuellen System. Bei der Implementierung erstellt InnDB ein Array für jede Transaktion, um den Moment zu speichern, in dem diese Transaktion beginnt. Es handelt sich derzeit um eine aktive (noch nicht übermittelte) Transaktion.
Wie bereits erwähnt, steigt die Transaktions-ID mit der Zeit strikt an. Der Maximalwert der übermittelten Transaktions-ID im System wird als Niedrigwasserstand des Arrays aufgezeichnet, und die erstellte Transaktions-ID + 1 wird als Hochwasserstand aufgezeichnet Ebene.
Dieses Ansichtsarray und der Hochwasserstand bilden die Konsistenzansicht (Leseansicht) der aktuellen Transaktion.
Zeichnen Sie ein Bild dieses Arrays. Es sieht folgendermaßen aus:
Die Regeln lauten wie folgt : 1 Wenn trx_id Der graue Bereich zeigt an, dass die trx_id der Version, auf die zugegriffen wird, kleiner ist als der ID-Wert des niedrigen Wasserstands im Array, dh die Transaktion, die diese Version generiert hat, wurde vor der Generierung festgeschrieben die Leseansicht, sodass diese Version sichtbar ist und von der aktuellen Transaktion abgerufen werden kann.
2 Wenn sich trx_id im orangefarbenen Bereich befindet, bedeutet dies, dass die trx_id der Version, auf die zugegriffen wird, größer ist als der ID-Wert des Hochwasserstands im Array, dh die Transaktion, die diese Version generiert hat, wurde nach der Leseansicht generiert wurde generiert, daher ist diese Version unsichtbar und kann von der aktuellen Transaktion nicht aufgerufen werden.
Das ist vielleicht etwas schwer zu verstehen: Drei Transaktionen fragen die gleichen Daten ab und aktualisieren sie zum leichteren Verständnis:
Die Originaldaten sind immer noch wie im Bild unten , aktualisiere die Informationen von Zhang San mit der ID = 2:
Zum obigen Bild möchte ich eine Frage stellen. Wie hoch sind unter den Isolationsstufen RC (Read Committed) und RR (Repeatable Read) die Abfragealterswerte zu den Zeitpunkten T4 bzw. T5? Was ist der aktualisierte Wert von T4? Denken Sie einen Moment darüber nach, ich glaube, jeder hat seine eigene Antwort. Die Antwort finden Sie am Ende des Artikels. Ich hoffe, Sie können mit Ihren eigenen Fragen weiterlesen.
2.3.2 Ergebnisse unter RR (Repeatable Read)
RR-Ebene erkennt die Abfrage nur die Daten, die vor dem Start der Transaktion übermittelt wurden, und die Ansicht wird erstellt, sobald die Transaktion gestartet wird. Verwenden Sie also den Befehl „Transaktion mit konsistentem Snapshot starten“ und die Ansicht wird sofort erstellt.
现在假设:
- 事务 A 开始前,只有一个活跃的事务,ID = 2,
- 已提交的事务也就是插入数据的事务 ID = 1
- 事务 A、B、C 的事务 ID 分别是 3、4、5
在这种隔离级别下,他们创建视图的时刻如下:
根据上图得,事务 A 的视图数组是[2,3];事务 B 的视图数组是 [2,3,4];事务 C 的视图数组是[2,3,4,5]。分析一波:
这样执行下来,虽然期间这一行数据被修改过,但是事务 A 不论在什么时候查询,看到这行数据的结果都是一致的,所以我们称之为一致性读。
其实视图是否可见主要看创建视图和提交的时机,总结下规律:
- 版本未提交,不可见
- 版本已提交,但在视图创建后提交,不可见
- 版本已提交,但在视图创建前提交,可见
2.3.2.1 快照读和当前读
事务 B 的 update 语句,如果按照上图的一致性读,好像结果不大对?
如下图周明,B 的视图数组是先生成的,之后事务 C 才提交。那就应该看不见 C 修改的 age = 23 呀?最后 B 怎么得出 24 了?
没错,如果 B 在更新之前执行查询语句,那返回的结果肯定是 age = 22。问题是更新就不能在历史版本更新了呀,否则 C 的更新不就丢失了?
所以,更新有个规则:更新数据都是先读后写(读是更新语句执行,不是我们手动执行),读的就是当前版本的值,叫当前读;而我们普通的查询语句就叫快照读。
因此,在更新时,当前读读到的是 age = 23,更新之后就成 24 啦。
2.3.2.2 select 当前读
除了更新语句,查询语句如果加锁也是当前读。如果把事务 A 的查询语句 select age from t where id = 2 改一下,加上锁(lock in mode 或者 for update),也都可以得到当前版本 4 返回的 age = 24
下面就是加了锁的 select 语句:
select age from t where id = 2 lock in mode;
select age from t where id = 2 for update;
Nach dem Login kopieren
2.3.2.3 事务 C 不马上提交
假设事务 C 不马上提交,但是 age = 23 版本已生成。事务 B 的更新将会怎么走呢?
事务 C 还没提交,写锁还没释放,但是事务 B 的更新必须要当前读且必须加锁。所以事务 B 就阻塞了,必须等到事务 C 提交,释放锁才能继续当前的读。
2.3.3 RC(读提交)下的结果
在读提交隔离级别下,查询只承认在语句启动前就已经提交完成的数据;每一个语句执行之前都会重新算出一个新的视图。
注意:在上图的表格中用于启动事务的是 start transaction with consistent snapshot 命令,它会创建一个持续整个事务的视图。所以,在 RC 级别下,这命令其实不起作用。等效于普通的 start transaction(在执行 sql 语句之前才算是启动了事务)。所以,事务 B 的更新其实是在事务 C 之后的,它还没真正启动事务,而 C 已提交。
现在假设:
- Bevor Transaktion A beginnt, gibt es nur eine aktive Transaktion, ID = 2,
- Die festgeschriebene Transaktion ist die Transaktions-ID der eingefügten Daten = 1
- Die Transaktions-IDs der Transaktionen A, B und C sind 3, 4, bzw. 5.
Unter dieser Isolationsstufe ist der Moment, in dem sie die Ansicht erstellen, wie folgt:
Gemäß dem Bild oben ist das Ansichtsarray von Transaktion A [2,3,4], aber seine Obergrenze ist 6 oder höher (erstellte Transaktions-ID + 1); das Ansichtsarray von Transaktion B ist [2,4]; Eine Analysewelle:
03 Die Schultern der Riesen cnblogs .com/xd502djj/p/6668632.html
blog.csdn.net/article /details/109044141
- blog.csdn.net/u014078930/article/details/99659272
-
- 04 Zusammenfassung
- Dieser Artikel behandelt Alle Aspekte von Transaktionen im Detail, wie zum Beispiel: vier Hauptfunktionen, Isolationsstufen, gelöste Parallelitätsprobleme, Einrichtung, Überprüfen der Isolationsstufe, Starten einer Transaktion usw. Darüber hinaus haben wir auch ein tiefes Verständnis dafür gewonnen, wie die beiden Isolationsstufen RR und RC erreicht werden? Einschließlich einer detaillierten Erklärung, wie MVCC, Undo-Log und Leseansicht zusammenarbeiten, um MVCC zu implementieren. Abschließend sprachen wir über Snapshot-Lesung, aktuelle Lektüre usw. Man kann sagen, dass hier alle Wissenspunkte im Zusammenhang mit Angelegenheiten vorhanden sind. Wenn Sie nach dem Lesen dieses Artikels immer noch nicht verstehen, kommen Sie und schlagen Sie mich!
- 【Verwandte Empfehlung:
- MySQL-Video-Tutorial
】