No entender el negocio, recomiendo la lectura de otro blog MySql nivel de aislamiento de transacción de cuatro
En primer lugar, hablar de la escena
Anote pseudo-código
la versión V1
código de nivel de servicio
. 1 pública clase del DemoService { 2 @Autowired 3. Privado DemoTask demoTask; . 4 @Autowired . 5 Privado DemoDao demeDao; . 6 7. @Transactional 8. Pública vacío Save () { 9. System.out.println ( "transacción de inicio de la ejecución" ); 10 Lista <DemoEntity > list = new new ArrayList (); // longitud asumida de una larga lista. . 11 demeDao.saveAll (Lista); // montón INSERT de datos 12 es System.out.println ( "begin asíncrona con el programa" ); 13 demoTask.task (); 14 System.out.println ( "transacción está acabada" ); 15 } 16 }
tareas asíncronas
. 1 @Component 2 pública clase DemoTask { 3. @Autowired 4. Privado DemoDao demeDao; . 5 . 6 @Async . 7 pública vacío de tareas () { . 8 el try { // Para facilitar la demostración, dejar que el hilo asíncrono de corriente a dormir por un tiempo . 9 del Thread.sleep (1000 ) ; 10 } la captura (InterruptedException E) { 11. e.printStackTrace (); 12 es } 13 es List <DemoEntity> Lista = demeDao.findAll (); 14 //pseudo código, estas tareas asíncronas será hacer una gran cantidad de computación basada en los resultados de la presentación paso anterior. 15 System.out.println ( "procesamiento asincrónico de transacciones" ); 16 } 17 }
Si el sql de impresión.
Una ejecución de la transacción se inicia 2 SQL INSERT INTO ....... . 3 SQL INSERT INTO ....... . 4 SQL INSERT INTO ....... . 5 SQL INSERT INTO ....... . 6 . ....... . 7 SQL INSERT INTO ....... . 8 SQL INSERT INTO ....... . 9 SQL INSERT INTO ....... 10 SQL INSERT INTO ...... . 11 transacción completa 12 de procesamiento de transacciones asíncronas
Registro de impresión se muestra arriba, no hay problema, ¿verdad?
Pero el resultado no es el caso, pero esto más adelante.
ejecución de la transacción se inicia
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
....... .
transacción está acabada
de procesamiento de transacciones asíncronas
........
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .. .....
Método uh (⊙o⊙) ... ¿Por qué saveAll () de forma asíncrona por qué se produce el efecto?
versión V2
público de clase del DemoService { @Autowired privada DemoTask demoTask; @Autowired privada DemoDao demeDao; // el transaccional @ pública vacío Save () { System.out.println ( "transacción de inicio de la ejecución" ); Lista <DemoEntity> Lista = new new ArrayList (); // asumido que la longitud de una larga lista. demeDao.saveAll (Lista); // de datos del lote INSERT System.out.println ( "comenzará asíncrona con el programa" ); demoTask.task (); System.out.println ( "transacción está acabada" ); } }
La línea clave de código está comentado @Transactional registros continúan viendo impresión
ejecución de la transacción se inicia
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
....... .
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
transacción está acabada
de procesamiento de transacciones asíncronas
Uh ser sincrónica, y sí, la @Transactional método está causando saveAll () se ha convertido en la clave para asíncrono, de por qué hemos llegado a ser asíncrono tiempo para estudiar su código fuente.
¿Qué enfoque de este documento es? Sigue leyendo
En segundo lugar, a partir de la línea de magia de código
Pegar el código de nuevo
// -Servicio capa de negocio público de clase del DemoService { @Autowired privada DemoTask demoTask; @Autowired privada DemoDao demeDao; @Transactional pública vacío Save () { System.out.println ( "transacción de inicio de la ejecución" ); Lista <DemoEntity> Lista = new new ArrayList (); // longitud asumida de una larga lista. demeDao.saveAll (lista); // insertar una gran cantidad de datos, la ejecución asíncrona INSERT System.out.println ( "inicia programa en ejecución asíncrono" ); demoTask.task (); System.out.println ( "transacción está acabada" ) ; } } //tareas asíncronas como @Component pública clase DemoTask { @Autowired privada DemoDao demeDao; @ // asíncrono ejecución asíncrona pública vacío de tareas () { try { // Para facilitar la presentación, dejar que el hilo asíncrono de corriente a dormir por un tiempo Thread.sleep (1000 ); } la captura (InterruptedException E) { e.printStackTrace (); } Lista <DemoEntity> = demeDao.findAll lista (); // pseudo-código, esto hará que un gran número de tareas asíncronas de acuerdo con el resultado del cálculo de la etapa anterior presentado. System.out.println ( "procesamiento asincrónico de Transacción" ); } }
Primera nota del código crítico marca roja
La primera es @Transactional causa demeDao.saveAll (Lista); // montón INSERT de los datos saveAll método () se ha convertido en la ejecución asíncrona.
En segundo lugar @Async es un método tarea () es asíncrono.
Para que quede claro que Save () es una transacción, de tareas () método es una transacción separada. Estos no explican, no creo que pueda ejecutar esta línea para ver los asuntos de identificación sql muestran transaction_isolation verá claramente que, efectivamente, dos transacciones separadas.
Entonces acariciado sobre la escena, el método de capa de servicio () Guardar para guardar un montón de datos, el método entonces la tarea () será aislado Guardar () para guardar los resultados, el siguiente paso de la operación.
Esta vez el problema salió, save () y de la tarea () método es asíncrona, ¿Cómo podemos controlar dos transacciones, para asegurar la operación de guardar () las confirmaciones de transacción (commit) para guardar los datos, puede comprobar en la tarea (asuntos) para salvar (guardar los resultados de los últimos métodos)?
Debido a que el uso de una base de datos PostgreSQL, el valor predeterminado lectura comprometida nivel de aislamiento se lee comprometida. significado comprometido a leer es decir, cuando el método Save () de las confirmaciones de transacción, que puede leer los datos de la tabla en el método () tarea que acaba de insertar. Así que ahora la pregunta de cómo garantizar el método Save () para enviar la transacción antes de la ejecución del método asíncrono tarea.
Luego hay que entender que el momento de la transacción. En diversas bases de datos, las transacciones son enviadas automáticamente de forma predeterminada, no van a hablar sobre cómo controlar manualmente las confirmaciones de transacción.
El momento de la transacción presentada : Cuando una transacción completa con éxito la implementación de todos sql, se enviará automáticamente la transacción.
Si usted entiende los problemas anteriores, es difícil pensar en lo que esa línea es un código mágico.
. 1 pública clase del DemoService { 2 @Autowired 3. Privado DemoTask demoTask; . 4 @Autowired . 5 Privado DemoDao demeDao; . 6 7. @Transactional 8. Pública vacío Save () { 9. System.out.println ( "transacción de inicio de la ejecución" ); 10 Lista <DemoEntity > list = new new ArrayList (); // longitud asumida de una larga lista. 11 demeDao.saveAll (Lista); // montón INSERT de datos de 12 demoDao.countByXXX (); // Esta es la línea de la magia de código, de hecho, sólo es necesario realizar una consulta en SQL 13 System.out.println ( "begin asíncrona al programa" ); 14 demoTask.task (); 15 System.out.println ( "transacción está acabada" ); 16 } 17 }
Esa línea de código es la línea mágica anteriormente, se acaba de ejecutar una instrucción de selección a (en sentido estricto esto debe cubrir sólo tiene que insertar los datos seleccionados, lo más fácil es para seleccionar la cuenta (*) de xxxtable). ¿Por qué?
Debido tabla de SQL va a cambiar esta línea de código para generar una instantánea de la última, es decir antes de la declaración de selección de SQL incluso asíncrono, se seleccione bloqueado aquí, hasta @Transactional causó saveAll (lista) se ejecuta de forma asíncrona completa. El hilo actual (por springboot, para la base de datos es la actualidad) continuará por la aplicación.
Con esa línea mágica de código, el diario se imprime de la siguiente manera:
ejecución de la transacción se inicia
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
....... .
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
SQL INSERT INTO .......
transacción está acabada
de procesamiento de transacciones asíncronas
En combinación con la operación anterior dedicar tiempo a seguir, sino el método () de la transacción, esto es terminado, y se debe presentar (commit) a.
Tal método tarea () de la transacción puede ser suavemente insertado sólo para ver los datos.
Además de esta línea de código lo solución mágica? Sí, la transacción está sujeto a control manual. Por supuesto, no se recomienda el control manual de los asuntos, ya que la transacción se deshace medios de control manual para controlar manualmente la transacción. Sin deshacer la transacción también no tiene sentido.
1 el Ejecutar ( "Inicio de Transacción") // asuntos abiertos 2 // Código de Negocios 3 EJECUTAR ( "el commit") // confirmar la transacción
En tercer lugar, la diferencia entre la transacción y el MySQL PostgreSQL
No entiendo la transacción puede leer otro artículo de blog: MySql nivel de aislamiento de transacción de cuatro
Asuntos PostgreSQL y MySQL diferencia es que PostgreSQL nivel de aislamiento de las transacciones se ha comprometido-leer, y el nivel por defecto de MySQL es lectura repetible.
Sus mecanismos internos son los mismos, incluyendo las cerraduras, MVCC, leyendo una instantánea de la lectura actual y así sucesivamente.
En cuarto lugar, extendida
Si el nivel de aislamiento en: repetible-lectura, cómo controlar los dos transacción asíncrona cometer orden.
Si utiliza: ReentrantLock o, sincronizado por supuesto, podemos resolver este problema.
Los comentarios se pueden discutir interés.
No se olvidó del corazón a temprana edad
Si el lugar equivocado también, por favor dejar un mensaje de corrección.
El original no es fácil, por favor indique la dirección original: https:////www.cnblogs.com/hello-shf/p/12543766.html