Mysql demuestra lectura sucia, lectura no repetible y lectura fantasma

Lo que quiero demostrar hoy es el nivel de aislamiento del aislamiento de transacciones de Mysql.
Introduzca brevemente las cuatro características principales de las transacciones.

Principio de transacción InnoDB

  • La transacción (Transacción) es una de las características importantes que distinguen a la base de datos del sistema de archivos La transacción convierte la base de datos de un estado de coherencia a otro estado de coherencia.
  • Cuando se envía la base de datos, se puede garantizar que se hayan guardado todas las modificaciones o que no se hayan guardado todas las modificaciones.

Características de la transacción (ACID)

  • Atomicidad: todas las operaciones de todo el asunto se envían correctamente o todas fallan y se revierten (no se producirá una ejecución parcial).
  • Coherencia: para varias transacciones ejecutadas en paralelo, el resultado de la ejecución debe ser coherente con el resultado de la ejecución en serie en un orden determinado.
  • Aislamiento (Aislamiento): La ejecución de la transacción no es interferida por otras transacciones, y los resultados intermedios de la ejecución de la transacción deben ser transparentes para otras transacciones.
  • Durabilidad: Una vez que se compromete una transacción, los cambios en los datos de la base de datos son permanentes. Incluso si el sistema de la base de datos encuentra una falla, la operación de confirmar la transacción no se perderá.
Nivel de aislamiento de transacciones
  • Lectura no confirmada: lectura sucia (READ UNCOMMITTED) lectura no confirmada

  • Enviar lectura: lectura no repetible (LEER COMPROMETIDA)

  • Lectura repetible: lectura fantasma (LECTURA REPETIBLE): este es el nivel de aislamiento de transacciones predeterminado de MySQL

  • Serialización legible (SERIALIZABLE) Serialización y lectura serial

    Bajo este nivel de aislamiento, los problemas de lectura sucia, lectura no repetible y lectura fantasma que aparecieron antes pueden resolverse, pero también causarán una gran cantidad de tiempos de espera y competiciones bloqueadas. Por lo general, no se recomienda usar

√ significa que sucederá, × significa que no sucederá

Nivel de aislamiento Lectura sucia No repetible Lectura fantasma
lectura no confirmada (lectura no confirmada)
leer comprometido ×
lectura repetible × ×
serializable (serializable) × × ×
表格借鉴的Java识堂(https://blog.csdn.net/weixin_44685869/article/details/104105291)

Algunos comandos de MySQL utilizados en este artículo

# 查看 MySQL 版本
select version()

# 查看 MySQL 隔离级别
SELECT @@tx_isolation

# MySQL在会话层面设置隔离级别
set session transaction isolation level 隔离级别名字

# 开启事务
start transaction

# 提交事务
commit

# 回滚事务
rollback
1234567891011121314151617

Cree bibliotecas, tablas y vistas.

# 创建 demo01 数据库
create database demo01

use demo01

# 创建测试表
create table test01(
	id int(3) not null primary key auto_increment,
	name varchar(64) default null,
	price int(7) default 0         # 这里不许有逗号
)ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;
1234567891011

Insertar datos iniciales

insert into test01(name,price) values('张三',100),('李四',0);
1
一切ok 开始干活

Lectura sucia

Los datos de la tabla son los siguientes, establezca el nivel de aislamiento en lectura no confirmada
Inserte la descripción de la imagen aquí

hora Cliente A (pestaña A) Cliente B (pestaña B)
T1 establecer el nivel de aislamiento de la transacción de la sesión leer sin confirmar; iniciar la transacción; actualizar test01 establecer el precio = precio + 100 donde id = 1; seleccionar * de test01 donde id = 1; Establecer como lectura no comprometida, dar cuenta de Zhang San +100, La salida es 200
T2 establecer el nivel de aislamiento de la transacción de la sesión leer no confirmado; iniciar la transacción; seleccionar * de test01 donde id = 1; la salida del saldo de la consulta es 200
T3 Retroceder
T4 cometer
T5 seleccione * de test01 donde id = 1; la salida del balance de consultas es 100

La lectura sucia se refiere a cuando una transacción está accediendo a datos, y los datos se modifican, y esta modificación no se ha enviado a la base de datos, en este momento, otra transacción también accede a los datos y luego los usa.

Dé otro ejemplo serio para probar el peligro
. Los datos de la tabla son los siguientes
Inserte la descripción de la imagen aquí

hora Cliente A (pestaña A) Cliente B (pestaña B)
T1 establecer el nivel de aislamiento de la transacción de sesión leído no confirmado; iniciar transacción; actualizar test01 set price = price - 100 donde id = 1; actualizar test01 set price = price + 100 donde id = 2;
T2 establecer el nivel de aislamiento de la transacción de sesión leído no confirmado; iniciar transacción; seleccione el precio de test01 donde id = 2; actualizar test01 set price = price - 100 donde id = 2; 更新 语句 被 阻塞
T3 Retroceder
T4 cometer

Una vez completada la ejecución, los datos en la base de datos son los siguientes
Inserte la descripción de la imagen aquí

hora Explicación
T1 1 a 2 turnos 100
T2 2. El saldo de 2 es suficiente para comprar 100 yuanes y la declaración de actualización está bloqueada.
T3 1 retrocede, el saldo de 1 se convierte en 100 y el saldo de 2 se convierte en 0
T4 2 Deducción exitosa, saldo 0-100 = -100

Está bien ahora, el banco perdió 100 yuanes sin motivo.

No repetible

Los datos de la tabla son los siguientes, establezca el nivel de aislamiento para confirmar la lectura

Inserte la descripción de la imagen aquí

hora Cliente A (pestaña A) Cliente B (pestaña B)
T1 establecer el nivel de aislamiento de la transacción de la sesión leer comprometido; iniciar la transacción; seleccionar * de test01 donde id = 2; La salida del saldo de la consulta es 0
T2 establecer el nivel de aislamiento de transacciones de sesión leído confirmado; iniciar transacción; actualizar test01 set price = price + 100 donde id = 2; seleccione * de test01 donde id = 2; cometer; 查询 余额 输出 100
T3 seleccione * de test01 donde id = 2; comprometerse; verificar la salida de saldo 100

Lectura no repetible significa que en la transacción 1, se lee un dato y, cuando la transacción 1 no ha finalizado, la transacción 2 también accedió a los datos, modificó los datos y los envió. Inmediatamente después, la transacción 1 vuelve a leer estos datos. Debido a la modificación de la transacción 2, los datos leídos dos veces en la transacción 1 pueden ser diferentes, por lo que se denomina lectura no repetible.

当然你可以在T2时间段客户端B修改完id=2的账户余额但没有commit的时候,在客户端A查询id=2的账户余额,发现账户余额为0,可以证明提交读这个隔离级别不会发生脏读。

可重复读级别

看一下可重复读是个什么过程?
表中的数据如下,设置隔离级别为可重复读
Inserte la descripción de la imagen aquí

时间 客户端A(Tab A) 客户端B(Tab B)
T1 set session transaction isolation level repeatable read; start transaction; select * from test01 where id = 2; 查询余额输出为0
T2 set session transaction isolation level repeatable read; start transaction; update test01 where set price = price + 100 where id = 2; select * from test01 where where id = 2; commit; 查询余额输出100
T3 select * from test01 where where id = 2; commit; 查询余额输出0

当我们将当前会话的隔离级别设置为可重复读的时候,当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。

但是在可重复读的隔离级别上,会产生幻读的问题。

幻读

设置隔离级别为可重复读

Inserte la descripción de la imagen aquí

所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。

用大白话解释一下,就是事务1查询id<10的记录时,返回了2条记录,接着事务2插入了一条id为3的记录,并提交。接着事务1查询id<10的记录时,返回了3条记录,说好的可重复读呢?结果却多了一条数据。

演示如何解决的幻读,表中的数据如下
Inserte la descripción de la imagen aquí
MySQL通过 MVCC 解决了这种情况下的幻读
MVCC 在我理解 就是类似于乐观锁

时间 客户端A(Tab A) 客户端B(Tab B)
T1 set session transaction isolation level repeatable read; start transaction; select count(*) from test01 where id <= 10; 输出2
T2 set session transaction isolation level repeatable read; start transaction; insert into test01 (id, name, price) values (3, “王五”, 0); select count(*) from test01 where id <= 10; commit; 输出3
T3 select count(*) from test01 where id <= 10; commit; 输出2

这种情况下的幻读被解决了,我再举一个例子

表中的数据如下

Inserte la descripción de la imagen aquí

时间 客户端A(Tab A) 客户端B(Tab B)
T1 set session transaction isolation level repeatable read; start transaction; select count(*) from account where id = 3; 输出为0
T2 set session transaction isolation level repeatable read; start transaction; insert into account (id, name, balance) values (3, “王五”, 0); commit;
T3 insertar en la cuenta (id, nombre, saldo) valores (3, "王 五", 0); clave primaria duplicada, error al insertar
T4 seleccione count (*) de la cuenta donde id = 3; la salida es 0
T5 Retroceder;

Seleccione si un registro existe, no existe y está listo para insertar este registro, pero cuando se ejecuta la inserción, se encuentra que el registro ya existe y no se puede insertar, esto es un problema.

Mucha gente tiende a confundir la lectura no repetible con la lectura fantasma, de hecho, las dos son algo similares. Pero la lectura no repetible se centra en la actualización y la eliminación, mientras que la lectura fantasma se centra en la inserción.

En general, la lectura fantasma significa que la transacción A opera con datos, la transacción B todavía puede usar insertar para insertar datos, porque se usan bloqueos de fila, por lo que los diversos problemas extraños causados ​​por esto son la lectura fantasma. Hay muchas manifestaciones, por lo que no las enumeraré. .

Cuando el nivel de aislamiento se establece en serializable, la transacción se ve obligada a ejecutarse en serie, evitando el problema de lectura fantasma mencionado anteriormente.

Dirección original de referencia: https://blog.csdn.net/zzti_erlie/article/details/88080822


La base de datos utiliza bloqueos para admitir una mejor concurrencia y proporcionar integridad y coherencia de los datos.
InnoDB es un motor de almacenamiento que admite bloqueos de fila. Los tipos de bloqueos son:

  • Cerradura compartida (S)
  • Cerradura exclusiva (X)
  • Intención compartida (IS)
  • Intención exclusiva (IX)

Para proporcionar una mejor simultaneidad, InnoDB proporciona lectura sin bloqueo: no es necesario esperar a que se libere el bloqueo en la fila de acceso, lea una instantánea de la fila. Este método se implementa a través de una función de InnoDB: MVCC.

InnoDB tiene tres algoritmos de bloqueo de filas:

  1. Bloqueo de registro: el bloqueo en un registro de una sola fila.
  2. Bloqueo de espacio: Bloqueo de espacio, bloquea un rango, pero no incluye el registro en sí. El propósito del bloqueo GAP es evitar que las dos lecturas actuales de la misma transacción provengan de lecturas fantasmas.
  3. Bloqueo de tecla siguiente: 1 + 2, bloquea un rango y bloquea el registro en sí. Para las consultas de fila, se utiliza este método y el objetivo principal es resolver el problema de la lectura fantasma.

Supongo que te gusta

Origin blog.csdn.net/weixin_47587864/article/details/108563655
Recomendado
Clasificación