1. Concepto
Serie de pasos (operaciones) necesarios para completar algo. Estas operaciones tienen éxito o fracasan al mismo tiempo.
2. Operaciones básicas de transacciones.
Zhang San y Li Si tienen cada uno 1.000 yuanes en sus cuentas. Ahora Zhang San transfiere 500 yuanes a Li Si.
-- 1 创建account表
create table tb_account(
id int(11) auto_increment,
user_name varchar(30) not null,
account_blance int(11) not null, -- 账户余额
primary key (id)
)ENGINE=INNODB,default charset =UTF8;
-- 2 插入数据
insert into tb_account(user_name,account_blance)
values('ZS',1000),('LS',1000);
-- 3 执行张三向李四转账500
-- ZS账户-500,LS账户+500
-- 下面两个update语句要么同时执行成功要么同时执行失败
-- 执行下列SQL语句会出现问题:张三的钱减少了,李四的钱没有加上。因为此时的两个update语句并没有使用事务来托管
update tb_account set account_blance=account_blance-500 where id=1;
-- 银行转帐异常情况:如机机房停电
update tb_account set account_blance=account_blance+500 where id=2;
3. Cuatro características de los asuntos
Atomicidad : cada paso de la transacción no se puede volver a dividir
Consistencia : Las cuentas de Zhang San y Li Si tienen un total de 2000 yuanes. No importa cuántas transferencias se realicen, el monto total permanece sin cambios.
Persistencia : cuando una transacción se ejecuta correctamente (se completa), los datos se conservarán en el archivo de datos del disco. Por ejemplo, si la transferencia se realiza correctamente: el saldo de Zhang San pasa a ser 500 y el saldo de Li Si pasa a ser 1500.
Aislamiento : la transacción A y la transacción B operan con un dato al mismo tiempo y no se afectan entre sí.
4. Cómo enviar transacciones,
1) Envío automático
No es necesario escribir una confirmación; la declaración DML se enviará automáticamente de forma persistente.
2) Envío manual
--El resultado de la consulta es 1 para envío automático y 0 para envío manual.
select @@autocommit;
- Modificar el método de envío (cambiar el envío automático al envío manual)
set @@autocommit = 0 ;
5. Operaciones básicas de transacciones.
1 Iniciar una transacción
start transaction;
2 Confirmar la transacción
commit;
3 transacción de reversión
rollback;
Nota: Una vez que utilice Iniciar transacción, para abrir una transacción, el envío automático no será válido.
Si todas las operaciones se ejecutan normalmente use commit; confirme la transacción
Cuando ocurre una excepción y se revierte una transacción, los datos (en este caso, la tabla tb_account) generalmente se revierten al estado anterior a que se iniciara la transacción.
6. Operación de transferencia
-- 1 开启事务
start transaction;
-- 2 执行SQL语句
update tb_account set account_blance=account_blance-500 where id=1;
手机转账异常情况:转账过程中手机没电了
update tb_account set account_blance=account_blance+500 where id=2;
-- 3 如果SQL语句全部执行成功就提交事务,如果其中任何一步执行失败,立刻回滚事务
-- 此时第一个update执行成功,第二个update语句执行失败了,并没有提交事务,查询结果如下:
select * from tb_account;
/*
+----+-----------+----------------+
| id | user_name | account_blance |
+----+-----------+----------------+
| 1 | ZS | 500 |
| 2 | LS | 1000 |
+----+-----------+----------------+
*/
-- 问题:张三账户的余额减少了,李四账户余额没有增加。这就是脏数据
-- 此时需要将脏数据回滚到开启事务之前
rollback;
-- 回滚完毕再次查询
select * from tb_account;
-- 此时事务回滚到开启之前的状态
/*
+----+-----------+----------------+
| id | user_name | account_blance |
+----+-----------+----------------+
| 1 | ZS | 1000 |
| 2 | LS | 1000 |
+----+-----------+----------------+
*/
-- 一个事务一旦开启了,在没有执行commit;或者rollback;之前事务不会结束
-- 相关面试题:工作中有没有用到事务?请解释事务的概念?不使用事务会发生什么问题?使用事务能够解决什么问题?解释事务的四大特征[隔离级别]?
7. Nivel de aislamiento de transacciones
nivel de aislamiento de transacciones |
lectura sucia |
lectura no repetible |
lectura fantasma |
lectura no confirmada |
Sí |
Sí |
Sí |
lectura comprometida |
No |
Sí |
Sí |
Lectura repetible |
No |
No |
Sí |
serializable |
No |
No |
No |
Nivel de aislamiento de consultas
select @@tx_isolation
En el trabajo: no se utiliza ni 1 ni 4, solo se cambia entre 2 y 3
El nivel de aislamiento de transacciones predeterminado de MySQL es 3 y el nivel de aislamiento predeterminado de Oracle es 2.
SELECT @@global.tx_isolation; //查询全局事务
SELECT @@session.tx_isolation; //查询当前会话事务
establecer el nivel de aislamiento de transacciones
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
//测试可以不用设置全局事务
SET GLOBAL TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
//(这个可以不用设,只设置上面一行就可以了进行测试了)
Lectura sucia:
Una transacción (A) lee datos no confirmados de otra transacción (B) (rompiendo el aislamiento).
Por ejemplo: la transacción A abre una transacción para transferencia y la instrucción DML se ejecuta exitosamente pero sin confirmación; la transacción B se abre en otra ventana y la instrucción Select se ejecuta para leer los datos de tb_account y el resultado de la lectura son los datos que la transacción A no se ha enviado.
Lectura no repetible:
Los datos leídos varias veces en la misma transacción son inconsistentes ( rompiendo la coherencia, actualizando y eliminando)
Por ejemplo: la transacción A abre una transacción para transferencia y la instrucción DML se ejecuta exitosamente pero sin confirmación; la transacción B se abre en otra ventana y la instrucción Select se ejecuta para leer los datos de tb_account y el resultado de la lectura es correcto (1000 , 1000).
Se envió una transacción en la transacción A. Luego la transacción B realiza la operación Seleccionar nuevamente y el resultado de la consulta es correcto (500,1500)
Problema: la transacción B realizó dos operaciones de selección en la tabla tb_account en una transacción y los resultados de la consulta de las dos operaciones fueron inconsistentes.
Lectura fantasma:
La transacción A inserta un dato y puede usar select para obtener el resultado. En este momento, la transacción B inserta un dato o una gran cantidad de datos casi al mismo tiempo. En este momento, la transacción A no puede ver la actualización de la transacción B. (rompiendo la consistencia, insertar ).
leer prueba de lectura sucia no confirmada:
Cuando se inicia una transacción, otra transacción puede leer las actualizaciones del extracto de esta transacción sin un envío confirmado.
¿Cómo solucionar el problema de la lectura sucia? Modificar el nivel de aislamiento de la transacción: lectura confirmada
set session transaction isolation level read committed;
¿Cómo solucionar el problema de lectura no repetible? Establezca el nivel de aislamiento de la transacción en "lectura repetible" lectura repetible
Demostración del problema de lectura fantasma:
Pruebas serializables
Puede resolver todos los problemas, pero es ineficiente, similar al sincronizado de Java.
Java usa sincronizado para bloquear objetos. MySQL usa serializable para bloquear la tabla. La transacción A inicia la transacción y realiza operaciones DML, pero no se envía. En este momento, la transacción B inicia la transacción y realiza la operación de selección, pero no se consulta ningún dato porque la tabla tb_account está ocupada (bloqueada) por la transacción A en este momento.
set session transaction isolation level serializable;