MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

青灯夜游
풀어 주다: 2023-02-10 19:55:17
앞으로
1369명이 탐색했습니다.

이 글은 MySQL의 트랜잭션 기능에 대해 이야기하고 다중 버전 동시성 제어 MVCC의 구현 원리를 소개합니다. 모든 분들께 도움이 되기를 바랍니다!

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

1. 개념

Transaction은 일반적으로 논리적 작업 집합 또는 단일 논리 단위로 수행되는 일련의 작업을 의미하며, 트랜잭션의 모든 작업은 분리할 수 없는 개체로 캡슐화됩니다. 실행 단위를 분할하면 이 단위의 모든 작업은 성공하거나 실패합니다. 작업 중 하나라도 실패하면 전체 트랜잭션이 롤백됩니다.

2. 트랜잭션 특성 및 유형 소개

2.1 트랜잭션 특성

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

Atomicity(원자성)

트랜잭션의 원자성이란 트랜잭션을 구성하는 모든 작업 또는 모든 작업을 의미합니다. 성공적으로 실행되거나 모든 실행이 실패합니다.

일관성

트랜잭션의 일관성이란 트랜잭션 실행 전후에 데이터가 항상 일관된 상태를 유지한다는 의미입니다.

격리

트랜잭션의 격리는 동시에 실행되는 두 트랜잭션이 서로 간섭하지 않는다는 것을 의미합니다. 즉, 하나의 트랜잭션이 실행되는 동안 다른 트랜잭션의 실행 프로세스 중간을 볼 수 없습니다.

?‍참고: MySQL是通过锁个MVCC트랜잭션 격리를 보장하는 메커니즘입니다.

지속성(기간)

트랜잭션의 내구성은 트랜잭션이 커밋되면 이 트랜잭션으로 인한 데이터 변경 사항이 데이터베이스에 유지되고 롤백되지 않음을 의미합니다.

2.2 두 가지 유형의 트랜잭션 소개

  • 로컬 트랜잭션
  • 분산 트랜잭션

로컬 트랜잭션

보통 관계형 데이터베이스를 기반으로 제어되는 트랜잭션을 전통적인 트랜잭션 또는 로컬 트랜잭션이라고 부를 수 있습니다.

로컬 트랜잭션 실행 프로세스

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

  • 클라이언트가 트랜잭션 작업을 시작하기 전에 연결 응답을 열어야 합니다.

  • 응답을 시작한 후 클라이언트는 트랜잭션을 시작하라는 명령을 시작합니다.

  • 트랜잭션이 시작된 후 클라이언트는 데이터를 처리하기 위해 다양한 SQL 문을 보냅니다.

  • 정상적인 상황에서 클라이언트는 트랜잭션을 커밋하라는 명령을 시작합니다. 롤백 트랜잭션 명령

  • 위 프로세스가 완료되면 세션을 닫습니다.

✔지역 업무는 자원 관리자가 현지에서 관리합니다.

로컬 트랜잭션의 단점은 다음과 같습니다.

  • 분산 트랜잭션을 처리하는 기능이 없습니다.
  • 트랜잭션 프로세스는 트랜잭션을 지원하는 하나의 데이터베이스에만 연결할 수 있으며 여러 트랜잭션 데이터베이스에 사용할 수 없습니다.

3. 동시 트랜잭션은 어떤 문제를 가져오나요?

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

업데이트 손실(더티 쓰기)

두 개 이상의 트랜잭션이 동시에 동일한 데이터 행을 운영하고 초기값을 제공하는 경우 선택한 값이 데이터 행을 업데이트하면 트랜잭션이 서로의 존재를 인식하지 못하는 것으로 간주되므로 마지막 업데이트 작업은 이전에 다른 트랜잭션이 완료한 업데이트 작업을 덮어씁니다.

예:

Zhang San의 계좌는 100위안입니다. 현재 거래 1과 거래 2의 두 가지 거래가 있습니다. 거래 1은 Zhang San의 계좌 잔액을 100위안 늘리는 것이고, 거래 2는 Zhang San의 잔액을 늘리는 것입니다. 100위안씩 200을 더합니다. 처음에는 거래 1과 거래 2가 Zhang San의 계좌 잔고인 100위안을 동시에 읽은 다음 거래 1과 거래 2가 각각 거래 2보다 먼저 Zhang Sanyue를 업데이트했다고 가정합니다. 최근에 제출된 거래는 300위안(일반적으로 400위안)입니다. 즉, 나중에 제출된 거래 2가 거래 1의 업데이트 작업을 덮어씁니다. 이것이 소위 업데이트 손실입니다. (더티 쓰기)는 본질적으로 쓰기 작업의 충돌입니다. 그러나 더티 쓰기를 해결하는 방법은 트랜잭션이 특정 순서로 쓰기 작업을 실행하도록 각 트랜잭션을 순차적으로 실행하는 것입니다.

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

Dirty read

트랜잭션은 다른 트랜잭션에서 커밋되지 않은 데이터를 읽습니다. 예: 거래 1이 Zhang San의 잔액에 100위안을 추가하고 있습니다. 이 거래가 제출되기 전에 다른 거래 2는 수정 중인 데이터를 읽습니다. 제어 중인 거래가 없으면 두 번째 거래에서 해당 데이터를 읽습니다. 제출되지 않은 데이터 클러스터를 처리하는 다음 단계에서는 커밋되지 않은 데이터에 대한 종속성이 생성됩니다. 이 현상을 일반적으로 Dirty Read脏读,也就是说:脏读是一个事务读取了另一个事务没提交的数据。

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

?脏读本质上是读写操作的冲突,解决方法是先写后读,也就是写完之后再读。

不可重复读

一个事务读取了某些数据,在一段时间后,这个事务再次读取之前读过的数据,此时发现读取的数据发生了变化,或者其中某些数据记录已经被删除,这种现象被称为:不可重复读,即同一个事务,使用同样的查询语句,在不同时刻读取到的结果不一致。

不可重复读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

幻读

一个事务按照相同的查询条件重新读取之前读过的数据,此时发现其他事务插入了满足当前查询条件的新数据,数据结果集变多,这种现象称为幻读,即一个事务两次读取一个范围的数据记录,两次读到的结果不同。

幻读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

那到这里,很多小伙伴就有疑问,同样本质都是读写操作冲突,解决方法是先读后写,不可重复读和幻读到底有何区别?,我下面见简单解释一下:

  • 1️⃣ 不可重复读的重点在于更新和删除操作,而幻读的重点在于插入操作。

  • 2️⃣ MySQL使用锁机制实现事务的隔离级别时,在可重复读隔离级别中,SQL语句第一个读取到数据后,会将相应的数据加锁,使得其他事务无法修改和删除这些数据,通过锁的方式实现可重复读。但是这种方法无法对新数据的插入加锁,如果事务1读取了数据,或者修改和删除了数据,事务2还可以进行插入操作,导致事务1莫名其妙地多了一条之前没有的数据,这就是幻读。

  • 3️⃣ 所以,幻读是无法通过锁机制来避免,需要使用串行化的事务隔离级别,但是这种事务隔离级别会大大降低数据库的并发能力。

✔MySQL是通过MVCC(多版本并发控制)机制来避免不可重复读和幻读的。

四、MySQL事务的隔离级别

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

使用下面的命令可以查询全局级别和会话级别的事务隔离级别:

# 默认数据库的事务隔离级别为:可重复读(REPEATABLE-READ)
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
로그인 후 복사

MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화

五、多版本并发控制MVCC

Multi-Version Concurrency Control多版本并发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。

MVCC比锁的优势

可以将MVCC라고도 합니다. 즉,

Dirty라고도 합니다. 읽기는 한 트랜잭션이 다른 트랜잭션에서 제출하지 않은 데이터를 읽는 경우입니다. 🎜🎜🎜MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화🎜< blockquote>🎜?더티 읽기(Dirty reading)는 본질적으로 읽기 작업과 쓰기 작업 간의 충돌입니다. 해결 방법은 먼저 쓴 다음 읽는 것, 즉 쓴 후에 읽는 것입니다. 🎜

🎜Non-repeatable read🎜🎜🎜A 트랜잭션은 일정 시간이 지나면 이전에 읽은 데이터를 다시 읽습니다. 읽은 데이터가 변경되었거나 일부 데이터 레코드가 삭제된 것을 발견한 경우 이러한 현상을 반복 불가능 읽기라고 합니다. 🎜즉, 동일한 트랜잭션이 동일한 쿼리 문을 사용하여 서로 다른 시간에 읽혀 결과가 일치하지 않습니다. . 🎜🎜
🎜반복되지 않는 읽기는 본질적으로 읽기와 쓰기 작업 간의 충돌입니다. 해결 방법은 먼저 읽고 쓰는 것, 즉 읽은 후에 쓰는 것입니다. 🎜

🎜Phantom reading🎜🎜🎜A 트랜잭션은 동일한 쿼리 조건에 따라 이전에 읽은 데이터를 다시 읽습니다. 이때 다른 트랜잭션에 현재 쿼리 조건을 만족하는 데이터가 삽입되면 데이터 결과 집합이 더 커집니다. 이러한 현상을 팬텀 읽기라고 합니다. 즉, 트랜잭션이 여러 데이터 레코드를 두 번 읽으면 결과가 달라집니다. 🎜
🎜환상 읽기는 본질적으로 읽기와 쓰기 작업의 충돌입니다. 해결 방법은 먼저 읽고 쓰기, 즉 읽은 후에 쓰는 것입니다. 🎜
🎜이 시점에서 많은 친구들이 동일한 본질은 읽기와 쓰기 작업의 충돌입니다. 해결책은 반복되지 않는 읽기와 환상 읽기의 차이점은 무엇입니까? 아래에서 간략하게 설명하겠습니다. 🎜
  • 🎜1️⃣ 반복 불가능 읽기의 초점은 업데이트 및 삭제 작업이고 팬텀 읽기의 초점은 삽입입니다. 운영. 🎜
  • 🎜2️⃣ MySQL이 잠금 메커니즘을 사용하여 트랜잭션 격리 수준을 구현할 때 반복 읽기 격리 수준에서 첫 번째 SQL 문이 데이터를 읽은 후 해당 데이터가 잠기므로 다른 트랜잭션이 불가능합니다. 이러한 데이터를 수정하거나 삭제하면 잠금을 통해 반복적으로 읽을 수 있습니다. 그러나 이 방법은 새 데이터의 삽입을 잠글 수 없습니다. 트랜잭션 1이 데이터를 읽거나 데이터를 수정 또는 삭제하는 경우 트랜잭션 2도 삽입 작업을 수행하여 트랜잭션 1이 설명할 수 없는 추가 데이터를 추가하게 될 수 있습니다. 이것은 환상의 독서입니다. 🎜
  • 🎜3️⃣ 따라서 잠금 메커니즘을 통해 팬텀 읽기를 피할 수 없습니다. 직렬화된 트랜잭션 격리 수준을 사용해야 하지만 이 트랜잭션 격리 수준은 데이터베이스의 동시성 성능을 크게 저하시킵니다. 🎜
🎜✔MySQL은 MVCC(다중 버전 동시성 제어) 메커니즘을 사용하여 반복 불가능한 읽기 및 팬텀 읽기를 방지합니다. 🎜

🎜4. MySQL 트랜잭션의 격리 수준🎜

🎜MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화🎜🎜전역 및 세션 수준 트랜잭션 격리 수준을 쿼리하려면 다음 명령을 사용하세요. 🎜
-- 事务A操作
START TRANSACTION;
SELECT * FROM account WHERE id = 1;     //在事务B提交之前执行
SELECT * FROM account WHERE id = 1;     //在事务B提交之后执行
COMMIT;
로그인 후 복사
로그인 후 복사
🎜MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화🎜

🎜5. 다중 버전 동시성 제어 MVCC🎜

🎜다중 버전 동시성 제어다중 버전 동시성 제어, MVCC는 동시성 제어 방법은 일반적으로 데이터베이스 관리 시스템에서 데이터베이스에 대한 동시 액세스를 달성하는 데 사용됩니다. 🎜

🎜잠금에 비해 MVCC의 장점🎜🎜🎜 MVCC를 행 수준 잠금의 절충안으로 생각하면 유용합니다. 대부분의 경우 잠금 사용을 피하고 오버헤드가 더 적습니다. 구현에 따라 비차단 읽기를 허용하고 쓰기가 발생하는 동안 필요한 레코드만 잠글 수 있습니다. 🎜

MVCC的实现原理

MVCC的是通过保存数据澡某个时间点的快照来实现的,也就是说,不管事务执行多长的时间,每个事务看到的数据都是一致的。根据事务的开始时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。InnonDB主要通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时的 实际时间 ,相反它只存储这些事件发生时的系统 版本号(version) 。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。

《高性能MySQL》书籍中介绍到:

MVCC只在REPEATABLE READREAD COMMITTIED两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不符合当前事务版本数据行,而SERIALIZABLE串行化隔离级别则会对所有读取的行都加锁。

接下来举个例子说明在可重复读事务隔离级别下,MVCC机制是如何完成增删改查操作的。

  • 查询操作(SELECT)

在查询操作中,InnoDB存储引擎跟根据以下两个条件查询对应的行记录,只有满足对应条件才会被返回:

1️⃣ 只查找不晚于当前事务版本的数据行,也就是说,InnoDB存储引擎只会查找版本号小于或者等于当前事务版本的数据行,这些数据行要么在该事务开始前就存在,要么就是事务本身插入或者更新的行。
2️⃣ 对于数据删除,数据行删除的版本要么还没有被定义,要么大于当前事务的版本号,只有这样才能确保事务读到的行,在事务开始前并没有被删除。

举个例子,存在 事务A事务B 两个事务,事务A中存在两套相同的SELECT语句,事务B存在一条UPDATE语句,事务A 的第一条查询语句在事务B提交之前执行,第二条查询语句在 事务B 提交之后执行,事务A 如下所示:

-- 事务A操作
START TRANSACTION;
SELECT * FROM account WHERE id = 1;     //在事务B提交之前执行
SELECT * FROM account WHERE id = 1;     //在事务B提交之后执行
COMMIT;
로그인 후 복사
로그인 후 복사

事务B:

-- 事务B操作
START TRANSACTION;
UPDATE account SET balance = balance+100 WHERE id = 1;
COMMIT;
로그인 후 복사

✔结论:如果没有使用MVCC机制,则事务A中的第一条SELECT语句读取的数据是修改前的数据,而第二条SELECT语句读取的是修改后的数据,两次读取的数据不一致,想想,那不就乱了吗?? 如果使用了MVCC机制,无论事务B如何修改数据,事务A的两条查询语句的到的结果始终是一致的。

  • 插入操作(SELECT)

在插入操作中,InnoDB会将新插入的每一条行记录的当前系统版本包保存为行版本号。

比如:向account表插入一条数据,同时MVCC的两个版本号分别为create_versiondelete_versioncreate_version代表创建行的版本号,delete_version代表删除行的版本号,另外还有一个事务ID字段,如下面所示:

INSERT INTO account(id, name, balance) values(1001, &#39;austin&#39;, 100);
로그인 후 복사

对应的版本号信息如下表:

idnamebalancetransaction_idcreate_versiondelete_version
1001austin10011未定义

可以看出,当向数据表新增记录时,需要设置保存行的版本号,而删除行的版本号未定义。

  • 更新操作(SELECT)

在更新操作中,InnoDB存储引擎会插入一行新记录,并保存当前系统的版本号为新记录行的版本号,同时保存当前系统的版本号到原来数据行作为删除标识。比如:将account数据表中id为1001的用户账户月增加100元,对应SQL如下:

UPDATE account SET balance = balance+100 WHERE id = 1001;
로그인 후 복사

执行SQL, 在MVCC机制下的更新操作如下表所示:

idnamebalancetransaction_idcreate_versiondelete_version
1001austin100112
1001austin20022未定义

可以明显看出,执行更新操作时,MVCC机制是先将原来的数据复制一份,将balance字段增加100后,再讲create_version字段的值设置为当前系统的版本号,而delete_version字段的值未定义。

注意的是:原来的行会被复制到Undo Log中。

  • 删除操作(SELECT)

在删除操作中,InnoDB存储引擎会保存删除的每一个行记录当前的系统版本号,作为删除标识。比如:删除account数据表中id为1001的数据,SQL如下所示:

DELETE FROM account WHERE id = 1001;
로그인 후 복사

对应MVCC机制下的删除操作如下表所示:

id name balance transaction_id create_version delete_version
1001 austin 200 3 2 3

可以看出,当删除数据表数据行时,MVCC机制会将当前系统的版本号写入删除数据行版本字段delete_version中,以此来表示当前数据行已经被删除。

六、总结

本文主要讲述了事务的特性、类型和本地事务和分布式事务的区别,通过不同的示例解释并发事务带来的更新丢失、脏读、不可重复读、幻读的问题,同时介绍了多版本并发控制MVCC的实现原理,如果文章对你有帮助,感谢点赞?+评论?+收藏❤,我是:?‍?austin流川枫,我们下期见!

【相关推荐:mysql视频教程

위 내용은 MySQL의 트랜잭션 기능 및 구현 원칙에 대한 심층적인 대화의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!