relación transacción nivel de aislamiento MySQL y primavera Introducción (reimpresión)

Transferencia: https://blog.csdn.net/hellozhxy/article/details/81081187

Muy buen artículo, aprender acerca

Introducción nivel de aislamiento

Niveles de aislamiento lectura sucia lectura no repetible la magia de lectura
Lectura no confirmada (lectura no confirmada) posible posible posible
Lectura confirmada (lectura confirmada) imposible posible posible
Lectura repetible (Lectura repetible) imposible imposible posible
Serialización (la Serializable) imposible imposible imposible
  1. sucia datos de las lecturas están permitidas, que es posible leer las transacciones no confirmadas de la modificación de otras sesiones: la lectura no confirmada (lectura no confirmada)
  2. Lectura confirmada (Lectura confirmada): sólo se puede leer los datos ya presentados. La mayor parte de Oracle y otras bases de datos es el nivel por defecto (no lectura repetible)
  3. Lectura repetible (repetidos de lectura): Lectura repetible. Dentro de la misma hora de inicio consulta de movimientos de la transacción son consistentes, InnoDB el nivel predeterminado. En el estándar SQL, el nivel de aislamiento elimina lectura no repetible, pero hay lecturas fantasma, pero InnoDB resuelve el fantasma de lectura
  4. Leer serie (Serializable): totalmente serializado leer, cada lectura tendrá que obtener un bloqueo a nivel de tabla compartida, leer y escribir se bloquean mutuamente

La próxima vez para verificar las características de cada nivel de aislamiento, en primer lugar construir todo nos dejó una mesa, hemos establecido una cuenta para probar nuestro nivel de cuenta de aislamiento de transacción tabla:

1 
2 
3 
4 
5 
6 
7
Crear cuenta TABLA ( 
    `int id` (11) NOT NULL AUTO_INCREMENT, 
    ` varchar customer_name` (255) NOT NULL, 
    `money` int (11) NOT NULL, 
    PRIMARY KEY (` id`), 
    UNIQUE `uniq_name` USO BTREE ( CUSTOMER_NAME) 
) ENGINE = `InnoDB` AUTO_INCREMENT = 10 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT = COMPACT CHECKSUM = 0 DELAY_KEY_WRIT

RU (leer no comprometidos) leer nivel de aislamiento no comprometida

En primer lugar, abrimos la consola A, a continuación, establecer el nivel de aislamiento sesión para leer no comprometidos; entonces la misma consola abierta B, conjunto a la lectura no comprometida;

1 
2 
3 
4 
5 
6 
7 
8 
9 
10
mysql> conjunto de nivel de aislamiento de transacción sesión de lectura no comprometida; 
Query OK, 0 filas afectadas (0,03 seg) 
 
mysql> SELECT @@ session.tx_isolation; 
+ ------------------------ + 
| @@ session.tx_isolation | 
+ ------------------------ + 
| LEER-UNCOMMITTED | 
+ ------------------------ + 
1 filas en el conjunto (0,03 seg)

Nuestro nivel de aislamiento de dos consola se lee no comprometidos, la siguiente prueba que va a ocurrir nivel RU

resumen:

Modo se puede encontrar en el RU, una transacción de lectura a otro no comprometida (el commit) los datos, lo que resulta en lectura sucia. Si la transacción B se deshace, causará inconsistencias en los datos. RU es el nivel más bajo de aislamiento de transacción.

RC (lectura confirmada) nivel de aislamiento READ COMMITTED

Ahora vamos a nivel de aislamiento se establece en RC (lectura confirmada)

1
conjunto sesión de nivel de aislamiento de lectura no confirmada;


resumen

Nos modo RC, se puede encontrar. Cuando no hay datos presentados revisados ​​se comprometen en la consola B, consolar Una lectura es inferior a los datos modificados, lo que evita la lectura sucia en el modo de RU, pero hay un problema nos encontraremos con la misma transacción en la consola A en. Dos de selección de datos no es lo mismo, hay un problema que no se puede repetir .PS leer: RC nivel de aislamiento es la base de datos Oracle nivel de aislamiento predeterminado.

RR (Lectura repetible) Nivel de Lectura repetible Aislamiento


resumen:

En el nivel de RR, se aborda el problema de la lectura no repetible, que en este nivel de aislamiento, en una transacción que podemos garantizar que será capaz de obtener los mismos datos (incluso si tiene otros asuntos de modificar nuestros datos). Pero no puede evitar lecturas fantasma, fantasma lee explicación simple es que hay nuevos datos en el tiempo, no hay ninguna garantía de inconsistente dos veces para obtener los datos, pero diferentes bases de datos tienen diferentes implementaciones para diferentes niveles de RR, a veces más o cerraduras gap para evitar lecturas fantasma.

InnoDB resolver el fantasma de lectura

La definición previa de nivel de RR es probable que lea los productos fantasma, esto es aparecerá la definición tradicional de nivel de RR. Sin embargo, el uso de múltiples versiones MVCC control de concurrencia resolvió este problema en el motor InnoDB


Es que las lecturas fantasma que? En la definición estándar de nivel de aislamiento RR no puede ser resuelto lectura fantasma problema, por ejemplo, quiero asegurar a la lectura repetible, por lo que podemos añadir una cerradura (entre 1 y 11) en el rango de nuestro conjunto de resultados, evitando los cambios de datos. Pero nosotros después de todo, en realidad no bloquear la tabla, insertar los datos de modo que no podemos garantizar que no se inserta. Así es la existencia de problemas de lectura fantasma. Pero resuelve INNODB el problema de la lectura fantasma, con base en MVCC (control de concurrencia multi-versión): En InnoDB, añadirá dos valor oculto adicional después de cada fila de datos para lograr MVCC, estos dos valores de una línea de registros de datos cuando fue creado, además de un registro de datos cuando esta línea caducado (o eliminado). En la práctica, el almacenamiento no es el tiempo, pero el número de versión de la transacción, cada abrir una nueva transacción, el número de versión de transacción se incrementa. Así que cuando llevamos a cabo la actualización, el número de versión de la transacción actual se ha actualizado? Por lo tanto, se puede considerar de lectura fantasma? ? (Dudoso) principalmente brecha de bloqueo brecha de lectura fantasma + MVCC resolver el problema?

nivel de aislamiento de serie:

todo de serie, el más alto nivel de aislamiento, el peor desempeño

Problemas?

En el modelo RR, aunque evitamos la lectura fantasma, pero hay un problema, obtenemos los datos en lugar de datos en datos en tiempo real, si es más sensible a los servicios de datos en tiempo real, lo que es poco realista.
Por este camino leer datos históricos, lo llamamos una lectura instantánea (snapshot de lectura), y leer la forma en que la versión actual de los datos en la base de datos, llamadas la lectura actual (lectura actual). Es claro que en MVCC en:

  • Las instantáneas leen: que seleccione
    • seleccionar * de la tabla ... .;
  • La lectura actual: leer especial, insertar / actualizar / operaciones de borrado, pertenecen a la lectura actual, los datos actuales se procesan, necesidad de bloqueo.
    • SELECT * FROM tabla donde? bloquear en modo compartido;
    • SELECT * FROM tabla donde? para la actualización;
    • insertar;
    • actualizar;
    • Eliminar;

nivel de aislamiento en realidad define el nivel de la lectura actual, MySQL con el fin de reducir el procesamiento de bloqueo (incluyendo la espera de otro bloqueo) tiempo, mejorar la concurrencia, introdujo el concepto de una lectura instantánea, por lo que no seleccione bloqueado. La actualización, insertar la "lectura actual" necesita módulos adicionales para resolver.

Por ejemplo, tenemos el siguiente escenario de negocio de venta, un solo producto de nuestro equipo operativo, tenemos que primero compruebe hasta qué punto el número de órdenes de la izquierda y luego el próximo single.

Transacción 1:

1 
2
seleccionar num de t_goods donde id = 1; 
t_goods actualización del conjunto num = nú- $ myNum donde id = 1;

Transacción 2:

1 
2
seleccionar num de t_goods donde id = 1; 
t_goods actualización del conjunto num = nú- $ myNum donde id = 1;

Suponiendo que este número sólo una vez, nuestro próximo single es solamente 1. Si en el caso de transacciones simultáneas 1 hay una sola consulta para prepararse para el siguiente sencillo, pero esta vez la transacción 2 ha sido presentado. Se convierten en órdenes de 0. 1 en esta actualización de la ejecución de transacciones, que causará un accidente.

  1. Después de la finalización de la liberación de bloqueo es el uso para bloqueo de actualización contra una transacción de los productos básicos: 1 solución al problema (bloqueo pesimista). Recuerde que donde hay índice de condiciones, de lo contrario, se bloqueará toda la tabla.
  2. Solución 2 (bloqueo optimista): tabla de la base para añadir un campo de versión. A continuación, volver a escribir el código SQL:
1 
2
seleccionar num, versión de t_goods donde id = 1; 
t_goods actualización del conjunto num = num-1, versión = verison + 1 donde id = 1 y la versión = $ {version}

mecanismo de resorte transacción

primavera para una serie de transacciones procesadas

nivel de aislamiento

Cuando se procesa en múltiples transacciones bloquear los datos, para asegurar la unidad del tiempo de procesamiento de datos sólo una transacción, hay diferentes situaciones para diferentes cerraduras

DEFAULT (predeterminado): Usar el nivel de aislamiento de base de datos subyacente, el uso de MySQL select @@ tx_isolation puede consultar el nivel de aislamiento actual

READ_COMMITTED: lectura confirmada, leer los datos ya se han presentado pueden prevenir las lecturas sucias, pero no repetible de lectura y lectura fantasma

READ_UNCOMMITTED: Lectura no confirmada, no hay datos se puede leer, presentada, con menos

REPEATABLE_READ: Lectura repetible, después de leer el bloqueo automático, otras transacciones no pueden ser modificados para hacer frente a la lecturas sucias, lectura no repetible

SERIALIZABLE: serialización, una fila de una ejecución de transacciones, una ejecución de transacciones después de la finalización de la próxima

mecanismo de propagación de Transacción

operaciones de bases de datos en el servicio, la forma de gestionar los asuntos de las dos operaciones

REQUERIDO (por defecto): Si una transacción no está en transacción abierta, cualquier transacción que se añade automáticamente a la

REQUIRES_NEW: Para la persona que llama, la persona que llama, independientemente de si hay una transacción, la persona que llama a crear un nuevo negocio.

OBLIGATORIO: Utilice la transacción actual, si no hay ninguna transacción, una excepción.

Anidadas transacciones, transacciones anidadas ejecutan si la hay, si no el nuevo

SOPORTES: el apoyo a la transacción actual, si no hay ninguna transacción se ejecuta de una manera no transaccional.

NOT_SUPPORTED: realizar una operación de una manera no transaccional, si existe la transacción actual, puso la transacción actual en espera.

NUNCA: para llevar a cabo de forma no transaccional, si existe la transacción actual, se produce una excepción.

servicios de gestión de la moda de primavera.

transacciones programáticas

programática de transacciones es el uso de los asuntos relacionados con la codificación manual de lógica de negocio, este enfoque es más complicado, largo aliento, pero más flexible y puede ser controlado (favorita)

1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13
pública testTransactionTemplate void () { 
 
  TransactionTemplate transactionTemplate = new TransactionTemplate (txManager); 
  transactionTemplate.setIsolationLevel (TransactionDefinition.ISOLATION_READ_COMMITTED); //设置事务隔离级别
  transactionTemplate.setPropagationBehavior (TransactionDefinition.PROPAGATION_REQUIRED); //设置为requerido传播级别
  .... 
  transactionTemplate.execute (nuevo TransactionCallbackWithoutResult () { 
      @ Override 
      protected void doInTransactionWithoutResult (estado TransactionStatus) {//事务块
         JdbcTemplate .Update (INSERT_SQL, "test"); 
  }}); 
  
}

transacción declarativa

  1. Para evitar manualmente cada vez que escribimos código usando manera primavera AOP alrededor del proxy para cada método, el uso de configuración XML para evitar la necesidad de escribir código.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<tx:advice id="txAdvice" transaction-manager="txManager"> 
<tx:attributes>  <!--设置所有匹配的方法,然后设置传播级别和事务隔离-->
           <tx:method name="save*" propagation="REQUIRED" /> 
           <tx:method name="add*" propagation="REQUIRED" /> 
           <tx:method name="create*" propagation="REQUIRED" /> 
           <tx:method name="insert*" propagation="REQUIRED" /> 
           <tx:method name="update*" propagation="REQUIRED" /> 
           <tx:method name="merge*" propagation="REQUIRED" /> 
           <tx:method name="del*" propagation="REQUIRED" /> 
           <tx:method name="remove*" propagation="REQUIRED" /> 
           <tx:method name="put*" propagation="REQUIRED" /> 
           <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> 
           <tx:method name="count*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="list*" propagation="SUPPORTS" read-only="true" /> 
          <tx:method name="*" propagation="SUPPORTS" read-only="true" /> 
       </tx:attributes> 
</tx:advice> 
<aop:config> 
       <aop:pointcut id="txPointcut" expression="execution(* org.transaction..service.*.*(..))" /> 
       <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut" /> 
</aop:config>
  1. 同时也可以用注解的方式
1
<tx:annotation-driven transaction-manager="transactioManager" /><!--开启注解的方式-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
   @AliasFor("transactionManager")
   String value() default "";
   @AliasFor("value")
   String transactionManager() default "";
   Propagation propagation() default Propagation.REQUIRED;//传播级别
  
   Isolation isolation() default Isolation.DEFAULT;//事务隔离级别
   int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;//事务超时时间
   boolean readOnly() default false;//只读事务
   Class<? extends Throwable>[] rollbackFor() default {};//抛出哪些异常 会执行回滚
   String[] rollbackForClassName() default {};
   Class<? extends Throwable>[] noRollbackFor() default {};
   String[] noRollbackForClassName() default {};//不回滚的异常名称
 
}
//transaction注解可以放在方法上或者类上

我们在这里不对两种事务编程做过多的讲解

Spring事务传播:

事务传播行为:

Spring管理的事务是逻辑事务,而且物理事务和逻辑事务最大差别就在于事务传播行为,事务传播行为用于指定在多个事务方法间调用时,事务是如何在这些方法间传播的,Spring共支持7种传播行为
为了演示事务传播行为,我们新建一张用户表

1
2
3
4
5
6
EATE TABLE user (
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `username` varchar(255) NOT NULL,
    `pwd` varchar(255) NOT NULL,
    PRIMARY KEY (`id`)
) ENGINE=`InnoDB` AUTO_INCREMENT=10 DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ROW_FORMAT=COMPACT CHECKSUM=0 DELAY_KEY_WRITE=0;

Required:

必须有逻辑事务,否则新建一个事务,使用PROPAGATION_REQUIRED指定,表示如果当前存在一个逻辑事务,则加入该逻辑事务,否则将新建一个逻辑事务,如下图所示;

测试的代码如下,在account插入的地方主动回滚

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public int insertAccount(final String customer, final int money) {
    transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//设置为required传播级别
   int re= transactionTemplate.execute(new TransactionCallback<Integer>() {
        public Integer doInTransaction( TransactionStatus status) {
            int i = accountDao.insertAccount(customer, money);
            status.setRollbackOnly();//主动回滚
            return i;
        }
    });
    return re;
}
 public int inertUser(final String username, final String password) {
        transactionTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);//设置为required传播级别
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                int i = userDao.inertUser(username, password);
                int hahha = accountService.insertAccount("hahha", 2222);
//                status.setRollbackOnly();
                System.out.println("user==="+i);
                System.out.println("account===="+hahha);
            }
        });
        return 0;
    }

按照required的逻辑,代码执行的逻辑如下:

  1. 在调用userService对象的insert方法时,此方法用的是Required传播行为且此时Spring事务管理器发现还没开启逻辑事务,因此Spring管理器觉得开启逻辑事务
  2. 在此逻辑事务中调用了accountService对象的insert方法,而在insert方法中发现同样用的是Required传播行为,因此直接使用该已经存在的逻辑事务;
  3. 返回userService,执行完并关闭事务

所以在这种情况下,两个事务属于同一个事务,一个回滚则两个任务都回滚。

RequiresNew:

创建新的逻辑事务,使用PROPAGATION_REQUIRES_NEW指定,表示每次都创建新的逻辑事务(物理事务也是不同的)如下图所示:

Supports:

支持当前事务,使用PROPAGATION_SUPPORTS指定,指如果当前存在逻辑事务,就加入到该逻辑事务,如果当前没有逻辑事务,就以非事务方式执行,如下图所示:

NotSupported:

不支持事务,如果当前存在事务则暂停该事务,使用PROPAGATION_NOT_SUPPORTED指定,即以非事务方式执行,如果当前存在逻辑事务,就把当前事务暂停,以非事务方式执行。

Mandatory:

必须有事务,否则抛出异常,使用PROPAGATION_MANDATORY指定,使用当前事务执行,如果当前没有事务,则抛出异常(IllegalTransactionStateException)。当运行在存在逻辑事务中则以当前事务运行,如果没有运行在事务中,则抛出异常

Never

不支持事务,如果当前存在是事务则抛出异常,使用PROPAGATION_NEVER指定,即以非事务方式执行,如果当前存在事务,则抛出异常(IllegalTransactionStateException)

Nested:

嵌套事务支持,使用PROPAGATION_NESTED指定,如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则创建一个新的事务,嵌套事务使用数据库中的保存点来实现,即嵌套事务回滚不影响外部事务,但外部事务回滚将导致嵌套事务回滚。

Nested和RequiresNew的区别:

  1. RequiresNew每次都创建新的独立的物理事务,而Nested只有一个物理事务;
  2. Nested嵌套事务回滚或提交不会导致外部事务回滚或提交,但外部事务回滚将导致嵌套事务回滚,而 RequiresNew由于都是全新的事务,所以之间是无关联的;
  3. Nested使用JDBC 3的保存点(save point)实现,即如果使用低版本驱动将导致不支持嵌套事务。

    使用嵌套事务,必须确保具体事务管理器实现的nestedTransactionAllowed属性为true,否则不支持嵌套事务,如DataSourceTransactionManager默认支持,而HibernateTransactionManager默认不支持,需要设置来开启。

Supongo que te gusta

Origin www.cnblogs.com/libin2015/p/12556163.html
Recomendado
Clasificación