>  기사  >  데이터 베이스  >  MySQL 트랜잭션에 대한 가장 완전하고 자세한 설명

MySQL 트랜잭션에 대한 가장 완전하고 자세한 설명

藏色散人
藏色散人앞으로
2019-09-10 14:36:483207검색

거래란 무엇인가요?

거래를 설명하는 공식 MySQL 문장은 무엇인가요? MySQL 트랜잭션은 주로 대규모 작업과 복잡성이 높은 데이터를 처리하는 데 사용됩니다. 그렇다면 데이터의 양이 왜 그렇게 많습니까? 복잡성이 높은 이유는 무엇입니까? 제가 이해한 내용을 바탕으로 설명하겠습니다. 트랜잭션은 실제로 MySQL에서 데이터를 처리하는 방식으로, 데이터 무결성이 높고 데이터 간의 의존도가 클 때 주로 사용됩니다. 예를 들어, Xiao Zhang이 Xiao Li의 은행 카드로 200위안을 이체했는데, Xiao Zhang이 이체를 확인하기 위해 버튼을 클릭했을 때 시스템이 갑자기 중단되었습니다. 다음과 같은 몇 가지 잘못된 상황이 있습니다.

1. Xiao Zhang의 돈이 Xiao Li의 계좌로 이체되었지만 자신의 계좌에 있는 돈이 공제되지 않았습니다.

2. Xiao Zhang의 돈이 Xiao Li로 이체되지 않았습니다.

이러한 비즈니스 시나리오에는 MySQL 트랜잭션 유지 관리가 필요합니다. 기계가 실패하더라도 데이터는 여전히 정확합니다.

트랜잭션 사용 조건

MySQL이 필요합니다. 트랜잭션을 사용하려면 스토리지 엔진이 필요합니다. MySQL에서 지원됩니다. 현재 트랜잭션을 지원하는 MySQL 내장 스토리지 엔진으로는 InnoDB, NDB 클러스터 등이 있고, 타사 스토리지 엔진으로는 PBXT, XtrDB 등이 있습니다.

MySQL의 트랜잭션에는 다음과 같은 특성(ACID)이 있습니다.

원자성(원자성):

트랜잭션은 분할할 수 없는 최소 작업 단위로 간주되어야 하며 각 트랜잭션의 모든 작업은 성공 또는 성공이어야 합니다. 실패하면 일부 작업은 실패하고 일부 작업은 성공할 수 없습니다. 이것이 소위 원자성 개념입니다.

Consistency(일관성):

Consistency는 위의 예와 같습니다. 예외가 있더라도 데이터는 여전히 정확합니다. 즉, 트랜잭션 실행에 실패하더라도 데이터는 비정상적인 상황에 영향을 받지 않으며 항상 정확성을 유지합니다.

격리:

트랜잭션이 제출되지 않은 경우 모든 트랜잭션은 각각 격리됩니다.

내구성(durability):

트랜잭션이 제출되면 변경 사항이 데이터베이스에 영원히 저장됩니다.

트랜잭션의 격리 수준

MySQL의 격리 특성에 대해 이야기할 때. , 우리는 여러 수준의 격리에 대해 이야기해야 합니다. 이것이 관련된 이유는 다음과 같이 간단하게 이해할 수 있습니다. 동시에 트랜잭션 작업을 수행하라는 두 개의 요청이 있고 이 두 트랜잭션이 동일한 데이터 조각에 대해 작동하는 경우 최종 결과는 누구에 따라 결정됩니다. 승리할 것인가? 격리 수준에 따라 결과가 달라지므로 트랜잭션의 격리 수준도 매우 중요한 포인트입니다.

격리 수준은 다음과 같은 점으로 구분됩니다.

1. 트랜잭션에서 커밋되지 않은 읽기(READ UNCOMMITTED)

데이터에 대한 수정 사항이 제출되지 않더라도 수정 사항은 다른 거래에 계속 표시됩니다. 이 경우 더티 읽기가 발생하여 데이터 무결성에 영향을 미칠 수 있습니다.

예: Xiao Ming이 Alipay로 결제하는 경우 , 은행 카드 잔액을 확인한 결과 여전히 300 위안이 있었는데 실제로는 여자 친구가 은행 카드에 200 위안을 입금하고 있었기 때문이었습니다. 입금하고 롤백 작업을 클릭했습니다. Xiao Ming이 결제에 실패했습니다.

2. READ COMMITTED

거래가 시작되면 제출된 다른 거래만 볼 수 있습니다. 이 경우 반복되지 않는 읽기가 발생하기 쉽습니다(두 읽기의 결과가 다름)

예: 위의 동일한 예를 사용하면 여자 친구가 카드를 긁었을 때 카드 잔액은 100위안이었지만 최종 결제를 클릭하면 잔액이 부족하다는 메시지가 표시됩니다. 이때 카드에 있는 금액이 없어졌습니다. 이는 Xiao Ming의 여자 친구가 지불했을 때 Xiao Ming이 운영하는 거래가 아직 제출되지 않았기 때문에 Xiao Ming의 여자 친구는 다른 결과를 두 번 보았습니다.

3. 반복 읽기

기록된 결과는 모두 일관됩니다. 반복 읽기는 위의 반복 불가능한 읽기 상황을 해결할 수 있습니다. 그러나 트랜잭션이 특정 범위의 레코드를 읽을 때 다른 트랜잭션이 이 범위에 새로운 데이터를 삽입하는 경우가 있습니다. 트랜잭션이 데이터를 다시 읽으면 데이터가 처음 읽은 것보다 크다는 것을 알게 됩니다. 기록이 하나 더 있습니다. 이것은 소위 유령 판독입니다. 두 판독 결과가 일치하지 않습니다.

예: Xiao Ming의 여자 친구가 은행 카드 기록을 확인했을 때 Xiao Ming이 5개의 소비 기록을 보았습니다. 이번에는 소비기록에 기록이 되어 있었는데 여자친구가 다시 그 기록을 읽어보니 6개의 기록이 있었습니다.

4. 직렬화는 마치 대기열과 같아서 매번 거래가 대기열에 들어갑니다. 이전 트랜잭션이 제출된 후에만 다음 트랜잭션이 실행될 수 있습니다. 이 상황은 위의 가상 읽기 문제를 해결할 수 있지만 각 데이터 조각에 잠금을 추가하므로 많은 수의 잠금 시간 초과 및 잠금 경쟁이 발생할 수 있으며 특히 일부 높은 동시성 비즈니스 시나리오에는 적합하지 않습니다.

예: 우리가 은행에 돈을 입금하기 위해 줄을 설 때, 다음 사람은 이전 사람이 모든 작업을 마친 후에만 할 수 있습니다. 중간에 있는 사람들은 줄을 설 수 없고, 하나씩만 줄을 서면 됩니다. 실제로 소위 직렬 모드라는 것도 그런 개념입니다.

MySQL 트랜잭션에 대한 가장 완전하고 자세한 설명

MySQL 트랜잭션에 대한 가장 완전하고 자세한 설명

격리 요약

위의 내용에 따라 예를 들어, 우리가 찾는 것은 어렵지 않습니다. 더티 읽기(Dirty Read)와 반복 불가능 읽기(Non-Repeatable Read)는 데이터 업데이트에 중점을 두고, 팬텀 읽기(Phantom Read)는 데이터 삽입에 중점을 둡니다.

여러 스토리지 엔진에서 트랜잭션이 처리되는 방식

사용 조건에 따라 위의 트랜잭션에서 우리는 MyISAM 스토리지 엔진과 같은 일부 스토리지 엔진이 트랜잭션을 지원하지 않는다는 것을 알 수 있습니다. 트랜잭션에 트랜잭션 스토리지 엔진과 비트랜잭션 스토리지를 사용하는 경우 커밋은 정상적으로 진행될 수 있지만 비트랜잭션 스토리지 엔진을 롤백하면 응답 오류 메시지가 표시됩니다. # 🎜🎜#

트랜잭션 사용 방법

MySQL의 트랜잭션은 암시적으로 활성화됩니다. 즉, sql 문은 트랜잭션입니다. 실행이 완료되면 트랜잭션이 제출됩니다. 시연 중에 명시적으로 활성화했습니다.

MySQL의 자동 커밋

위에서 언급했듯이 MySQL의 트랜잭션은 암시적으로 활성화됩니다. 이는 각 SQL이 자동으로 제출된다는 의미입니다. 이를 해제하려면 자동 커밋 옵션을 설정해야 합니다.

// 查看autocommit配置值(1或者ON则表示开启)
mysql root@127.0.0.1:(none)> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | ON |
+---------------+-------+
1 row in set
Time: 0.018s
// 设置autocommit配置值
mysql root@127.0.0.1:(none)> set autocommit = 0;
Query OK, 0 rows affected
Time: 0.000s
mysql root@127.0.0.1:(none)> show variables like '%autocommit%';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit | OFF |
+---------------+-------+
1 row in set
Time: 0.013s

1 테이블 구조는 다음과 같습니다

mysql root@127.0.0.1:test> desc user;
+-------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | <null> | auto_increment |
| name | varchar(255) | YES | | <null> | |
| age | int(2) | YES | | <null> | |
+-------+--------------+------+-----+---------+----------------+
3 rows in set
Time: 0.013s
#🎜 🎜#SQL 문

CREATE TABLE `test`.`Untitled` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
`age` int(2) NULL DEFAULT NULL,
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

2. 트랜잭션 사용

MySQL을 사용하여 트랜잭션 구현

아래 코드에서, 우리는 주로 다음 작업을 수행합니다#🎜 🎜#

a. 거래 열기

b. 데이터 수정

c.

d. 데이터 롤백# 🎜🎜#

e. 데이터를 다시 쿼리하여 데이터가 수정 전 상태로 다시 변경되었는지 확인

f. #

g. 트랜잭션 제출

# 🎜🎜#h. 데이터를 쿼리하여 데이터가 마지막 수정 상태로 변경되었는지 확인합니다

i. #

j 롤백되었는지 확인하는 쿼리 및 데이터가 여전히 마지막 수정 상태이며 트랜잭션 롤백 실패

// 我们先查看表中的数据,id为1的age字段是12
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 12 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.013s
// 开启事务
mysql root@127.0.0.1:test> begin;
Query OK, 0 rows affected
Time: 0.001s
// 将id为1的age字段改为10
mysql root@127.0.0.1:test> update user set age=10 where id=1;
Query OK, 1 row affected
Time: 0.001s
// 再次查询数据时,发现数据改为修改后的值
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 10 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.012s
// 此时我们进行回滚操作
mysql root@127.0.0.1:test> rollback;
Query OK, 0 rows affected
Time: 0.001s
// 再次查询发现数据回到最初状态
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 12 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.019s
// 我们再次对数据进行修改
mysql root@127.0.0.1:test> update user set age=15 where id=1;
Query OK, 1 row affected
Time: 0.001s
// 此时将事务进行提交
mysql root@127.0.0.1:test> commit;
Query OK, 0 rows affected
Time: 0.000s
// 发现此时的数据变为我们最终提交的值
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 15 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.012s
// 我们尝试用刚才回滚的方式进行还原数据
mysql root@127.0.0.1:test> rollback;
Query OK, 0 rows affected
Time: 0.000s
// 发现数据无法回退了,仍然是提交后的数据
mysql root@127.0.0.1:test> select * from user;
+----+------+-----+
| id | name | age |
+----+------+-----+
| 1 | 张三 | 15 |
| 2 | 李四 | 15 |
+----+------+-----+
2 rows in set
Time: 0.017s

PHP 트랜잭션 예제 코드

<?php
// 连接MySQL
$mysqli = new mysqli(&#39;127.0.0.1&#39;, &#39;root&#39;, &#39;123456&#39;, &#39;test&#39;, 3306);
// 关闭事务自动提交
$mysqli->autocommit(false);
// 1.开启事务
$mysqli->begin_transaction();
// 2.修改数据
$mysqli->query("update user set age=10 where id=1");
// 3.查看数据
$mysqli->query("select * from user");
// 4.事务回滚
$mysqli->rollback();
// 5.查看数据
$mysqli->query("select * from user");
// 7.修改数据
$mysqli->query("update user set age=15 where id=1");
// 8.事务提交
$mysqli->commit();
// 9.事务回滚
$mysqli->rollback();
// 10.查看数据
$mysqli->query("select * from user");

거래 격리 수준 설정 방법

// 查看当前的事务隔离级别
mysql root@127.0.0.1:test> select @@tx_isolation;
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set
Time: 0.015s
// 设置隔离级别
set session transaction isolation level 隔离级别(上面事务隔离级别中的英文单词);

위 내용은 MySQL 트랜잭션에 대한 가장 완전하고 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 公众号 深夜有话聊에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제