affairs

The concept of business

  A transaction refers to a logical group of operations, and the units that make up this group of operations are either all successful or all unsuccessful .
  For example: A-B transfer, corresponding to the following two sql statements
    update from account set money=money+100 where name='B';
    update from account set money=money-100 where name='A';

Second, the operation transaction command in the MySQL database

  1. Write a test SQL script, as follows:

/*创建账户表*/
create table account(
    id int primary key auto_increment,
    name varchar(40),
    money float
);

/*插入测试数据*/
insert into account(name,money) values('A',1000);
insert into account(name,money) values('B',1000);
insert into account(name,money) values('C',1000);

  Next, we simulate the business scenario of A-B transfer in the MySQL database

2.1. Start transaction

  Use "start transaction" to start a transaction for the MySQL database, as follows:

  

  We first simulate the scenario of transfer failure in the database. First, execute the update statement to reduce the money of user A by 100 yuan, as shown in the following figure:

  

  Then we close the dos command line window of the current operation, which leads to the fact that the database transaction of the update statement just executed is not submitted, then our modification to user A is not a real modification, and the next time we query user A When the money is changed, it is still the previous 1000, as shown in the following figure:

  

2.2, commit the transaction (commit)

  Next, we simulate the successful scenario of A-B transfer in the database

  

  After we manually submitted the database transaction, the business operation of transferring 100 yuan from A to B was considered a real success, with 100 less in the A account and 100 more in the B account.

2.3, rollback transaction (rollback)

  

  By manually rolling back the transaction, all operations are invalidated, so that the data will return to the original initial state!

Third, the use of transactions in JDBC

  When the Jdbc program obtains a Connection object from the database, the Connection object will automatically submit the SQL statement sent on it to the database by default. If you want to turn off this default commit method and allow multiple SQLs to be executed in one transaction, you can use the following JDBC control transaction statement

  • Connection.setAutoCommit(false);//Start transaction (start transaction)
  • Connection.rollback();//Rollback transaction (rollback)
  • Connection.commit();//Submit the transaction (commit)

3.1, JDBC use transaction paradigm

  Demonstrate a bank transfer case in JDBC code, so that the following transfer operations are performed in the same transaction

  "update account set money=money-100 where name='A'"

  update account set money=money+100 where name='B'

  code show as below:

package me.gacl.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import me.gacl.utils.JdbcUtils;
import org.junit.Test;

/**
* @ClassName: TransactionDemo1
* @Description: 
* JDBC中使用事务来模似转帐 
    create table account(
        id int primary key auto_increment,
        name varchar(40),
        money float
    );
    insert into account(name,money) values('A',1000);
    insert into account(name,money) values('B',1000);
    insert into account(name,money) values('C',1000);
* @author: 孤傲苍狼
* @date: 2014-9-22 下午11:16:17
*
*/ 
public class TransactionDemo1 {

    /**
    * @Method: testTransaction1
    * @Description: 模拟转账成功时的业务场景
    * @Anthor:孤傲苍狼
    *
    */ 
    @Test
    public void testTransaction1(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        
        try{
            conn = JdbcUtils.getConnection();
            conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
            String sql1 = "update account set money=money-100 where name='A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();
            String sql2 = "update account set money=money+100 where name='B'";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();
            conn.commit();//上面的两条SQL执行Update语句成功之后就通知数据库提交事务(commit)
            System.out.println("成功!!!");  //log4j
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    /**
    * @Method: testTransaction1
    * @Description: 模拟转账过程中出现异常导致有一部分SQL执行失败后让数据库自动回滚事务
    * @Anthor:孤傲苍狼
    *
    */ 
    @Test
    public void testTransaction2(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        
        try{
            conn = JdbcUtils.getConnection();
            conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
            String sql1 = "update account set money=money-100 where name='A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();
            //用这句代码模拟执行完SQL1之后程序出现了异常而导致后面的SQL无法正常执行,事务也无法正常提交,此时数据库会自动执行回滚操作
            int x = 1/0;
            String sql2 = "update account set money=money+100 where name='B'";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();
            conn.commit();//上面的两条SQL执行Update语句成功之后就通知数据库提交事务(commit)
            System.out.println("成功!!!");
        }catch (Exception e) {
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
    
    /**
    * @Method: testTransaction1
    * @Description: 模拟转账过程中出现异常导致有一部分SQL执行失败时手动通知数据库回滚事务
    * @Anthor:孤傲苍狼
    *
    */ 
    @Test
    public void testTransaction3(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        
        try{
            conn = JdbcUtils.getConnection();
            conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
            String sql1 = "update account set money=money-100 where name='A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();
            //用这句代码模拟执行完SQL1之后程序出现了异常而导致后面的SQL无法正常执行,事务也无法正常提交
            int x = 1/0;
            String sql2 = "update account set money=money+100 where name='B'";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();
            conn.commit();//上面的两条SQL执行Update语句成功之后就通知数据库提交事务(commit)
            System.out.println("成功!!!");
        }catch (Exception e) {
            try {
                //捕获到异常之后手动通知数据库执行回滚事务的操作
                conn.rollback();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
}

 3.2. Set transaction rollback point

  In development, sometimes it may be necessary to manually set the rollback point of the transaction. In JDBC, use the following statement to set the rollback point of the transaction

  Savepoint sp = conn.setSavepoint();
  Conn.rollback(sp);
  Conn.commit();//After rollback, the database must be notified to commit the transaction
  Example of setting a transaction rollback point :

package me.gacl.demo;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;

import me.gacl.utils.JdbcUtils;
import org.junit.Test;

/**
* @ClassName: TransactionDemo1
* @Description: 
* JDBC中使用事务来模似转帐 
    create table account(
        id int primary key auto_increment,
        name varchar(40),
        money float
    );
    insert into account(name,money) values('A',1000);
    insert into account(name,money) values('B',1000);
    insert into account(name,money) values('C',1000);
* @author: 孤傲苍狼
* @date: 2014-9-22 下午11:16:17
*
*/ 
public class TransactionDemo2 {

    /**
    * @Method: testTransaction1
    * @Description: 模拟转账成功时的业务场景
    * @Anthor:孤傲苍狼
    *
    */ 
    @Test
    public void testTransaction1(){
        Connection conn = null;
        PreparedStatement st = null;
        ResultSet rs = null;
        Savepoint sp = null;
        
        try{
            conn = JdbcUtils.getConnection();
            conn.setAutoCommit(false);//通知数据库开启事务(start transaction)
            
            String sql1 = "update account set money=money-100 where name='A'";
            st = conn.prepareStatement(sql1);
            st.executeUpdate();
            
            //设置事务回滚点
            sp = conn.setSavepoint();
            
            String sql2 = "update account set money=money+100 where name='B'";
            st = conn.prepareStatement(sql2);
            st.executeUpdate();
            
            //程序执行到这里出现异常,后面的sql3语句执行将会中断
            int x = 1/0;
            
            String sql3 = "update account set money=money+100 where name='C'"; 
            st = conn.prepareStatement(sql3);
            st.executeUpdate();
            
            conn.commit();
            
        }catch (Exception e) {
            try {
                /**
                 * 我们在上面向数据库发送了3条update语句,
                 * sql3语句由于程序出现异常导致无法正常执行,数据库事务而已无法正常提交,
                 * 由于设置的事务回滚点是在sql1语句正常执行完成之后,sql2语句正常执行之前,
                 * 那么通知数据库回滚事务时,不会回滚sql1执行的update操作
                 * 只会回滚到sql2执行的update操作,也就是说,上面的三条update语句中,sql1这条语句的修改操作起作用了
                 * sql2的修改操作由于事务回滚没有起作用,sql3由于程序异常没有机会执行
                 */
                conn.rollback(sp);//回滚到设置的事务回滚点
                //回滚了要记得通知数据库提交事务
                conn.commit();
            } catch (SQLException e1) {
                e1.printStackTrace();
            }
            e.printStackTrace();
        }finally{
            JdbcUtils.release(conn, st, rs);
        }
    }
}

Fourth, the four characteristics of transactions (ACID)

4.1. Atomicity

   Atomicity means that a transaction is an indivisible unit of work, and the operations in the transaction either all succeed or all fail . For example, SQL statements in the same transaction, either all execute successfully, or all fail to execute

4.2. Consistency

The concept of transaction consistency on the    official website is that a transaction must transform the database from one consistent state to another . Taking the transfer as an example, A transfers money to B. Assuming that the sum of the money of the two users before the transfer is 2000, then after A transfers to B, no matter how the two accounts are transferred, the money of user A and the money of user B will be added. The total amount is still 2000, which is the consistency of the transaction.

4.3. Isolation

   The isolation of transactions is that when multiple users access the database concurrently, the transaction opened by the database for each user cannot be interfered by the operation data of other transactions, and multiple concurrent transactions must be isolated from each other.

4.4. Durability

  Durability means that once a transaction is committed, its changes to the data in the database are permanent, and even if the database fails, it should not have any impact on it.

  The most troublesome of the four characteristics of transactions is isolation. The following focuses on the isolation level of transactions.

5. Transaction isolation level

  When multiple threads open their own transactions to operate data in the database, the database system is responsible for isolating operations to ensure the accuracy of each thread when acquiring data.

5.1. Issues that may arise from transactions that do not consider isolation  

  If the transaction does not consider isolation, the following problems may arise:

  1. Dirty reads

     Dirty reads refer to a transaction that reads uncommitted data from another transaction .

     This is very dangerous. Suppose A transfers 100 yuan to B. The corresponding sql statement is as follows:
          1.update account set money=money+100 where name='B';    
          2.update account set money=money-100 where name= 'A';
        When the first sql is executed, and the second one has not been executed (when A has not submitted), if B queries his account at this time, he will find that he has an extra 100 yuan. If A waits for B to leave and then rolls back, B will lose 100 yuan.  

  2. Non-repeatable read

  Non-repeatable read refers to reading a row of data in a table within a transaction, and the results of multiple reads are different.
  For example, if the bank wants to check the balance of account A, the first time the account A is 200 yuan, then A has deposited 100 yuan into the account and submitted it. The bank then makes another inquiry, and now the account A is 300 yuan. If the two inquiries of the bank are inconsistent, it may be very confusing, not knowing which inquiry is accurate.
  The difference between non-repeatable read and dirty read is that dirty read is to read the uncommitted dirty data of the previous transaction, while non-repeatable read is to re-read the data that has been committed by the previous transaction .
  Many people think that this situation is correct, no need to be confused, of course, the latter shall prevail. We can consider such a situation. For example, the banking program needs to output the query results to the computer screen and to the file respectively. As a result, the two queries performed against the output destination in one transaction are inconsistent, resulting in inconsistent results in the file and the screen. If the results are inconsistent, the bank staff will not know which one to take.

  3. Virtual reading (phantom reading)

  A virtual read (phantom read) refers to reading data inserted by another transaction within a transaction, resulting in inconsistent reading before and after .
  For example, if C’s deposit is 100 yuan and has not been submitted, then the bank makes a report and counts the total amount of all users in the account table as 500 yuan, and then C submits it. At this time, the bank counts and finds that the account is 600 yuan, which will also cause the bank to not know the false reading. What to do, in the end which shall prevail.

5.2, transaction isolation setting statement

  The MySQL database defines four isolation levels:

  1. Serializable (serialization): It can avoid the occurrence of dirty reads, non-repeatable reads, and virtual reads.
  2. Repeatable read: It can avoid the occurrence of dirty reads and non-repeatable reads.
  3. Read committed (read committed): to avoid dirty reads.
  4. Read uncommitted: The lowest level, none of the above conditions can be guaranteed.

  MySQL database query current transaction isolation level: select @@tx_isolation

  E.g:

  

  The default transaction isolation level of the mysql database is: Repeatable read (repeatable read)

  MySQL database set transaction isolation level: set transaction isolation level isolation level name

  E.g:

  

5.3. Use MySQL database to demonstrate concurrency issues under different isolation levels

  Open two windows at the same time to simulate 2 users accessing the database concurrently

1. When the isolation level of the transaction is set to read uncommitted, it will cause dirty reads, non-repeatable reads and virtual reads

  A window
    set transaction isolation level read uncommitted;--Set the database isolation level of user A to Read uncommitted (read uncommitted)
    start transaction;--Open transaction
    select * from account;--Query the existing money in account A, transfer Go to the B window to operate
    select * from account--it is found that a is more than 100 yuan. At this time, A has read the uncommitted data of B (dirty read)

  B window
    start transaction;--Open transaction
    update account set money=money+100 where name='A';--Do not submit, go to A window to query

2. When the isolation level of the transaction is set to read committed, it will cause non-repeatable reads and virtual reads, but avoid dirty reads

  A window
    set transaction isolation level read committed;
    start transaction;
    select * from account;--found that account a is 1,000 yuan, go to window b to
    select * from account;-- found that account a has more than 100, at this time, a read Data submitted by other transactions, read account a twice and read different results (non-repeatable read)
  window B
    start transaction;
    update account set money=money+100 where name='aaa';
    commit;--turn to a window

3. When the isolation level of the transaction is set to repeatable read (mysql default level), virtual reads will be triggered, but dirty reads and non-repeatable reads are avoided.

  A window
    set transaction isolation level repeatable read;
    start transaction;
    select * from account;-- found that the table has 4 records, go to the b window
    select * from account;-- may find that the table has 5 records, this time a occurred Read the data inserted by another transaction (virtual read)
  window B
    start transaction;
    insert into account(name,money) values('ggg',1000);
    commit;--Go to window a

4. When the isolation level of the transaction is set to Serializable, all problems will be avoided

  A window
    set transaction isolation level Serializable;
    start transaction;
    select * from account;--Go to b window

  B window
    start transaction;
    insert into account(name,money) values('ggg',1000);--It is found that it cannot be inserted, Only wait for a to end the transaction before inserting

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325175111&siteId=291194637