1. O conceito de negócio:
Um conjunto de unidades de operação lógica quando os dados transitam de um estado para outro.
2. Princípios de processamento de transações:
É garantido que todas as transações são executadas como uma unidade de operação, mesmo que ocorra uma falha, este princípio de disposição não pode ser alterado. Ou todos os dados relacionados à transação são modificados e confirmados para sempre , ou todas as transações são revertidas para o estado em que a transação não foi executada.
3. Essas operações afetarão o envio do banco de dados
(1). Uma vez que a conexão com o banco de dados é desconectada, os dados no banco de dados serão enviados
(2) A operação .DDL é concluída, os dados são enviados automaticamente e não podem ser revertidos
(3) O padrão da operação .DML é commit, mas você pode definir auto commit não permitido por set auto commit = false;
4. Simule o envio da transação
Diagrama do processo de execução da transação:
Método de atualização genérico contendo transações
/**
* 包含事务的通行的方法实现增删改
* @param conn 从外部传入的数据库连接,意图在执行完一次DML操作时,数据库的连接不会断开,
* 确保事务不会因为连接断而出现提交的现象
* @param sql 增删改语句
* @param args 占位符?个数不一定,根据sql占位符的个数,传入对应数量object
*/
public static int update(Connection conn,String sql,Object... args){
int temp = -1;
PreparedStatement pst = null;
try{
//2.预编译sql语句
pst = conn.prepareStatement(sql);
//3.填充占位符
for (int i = 0; i < args.length; i++) {
pst.setObject(i+1,args[i]);
}
//4.执行
/*
pst.execute();如果是查询操作返回的是true
如果是更新操作返回的是false;
pst.executeUpdate();返回执行操作以后受影响的行数
*/
// pst.execute();
temp = pst.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}finally {
//5.释放资源
closeResource(null,pst);
}
return temp;
}
(1) Simular a operação de transferência de 100 yuans de 102 para 103 em circunstâncias anormais;
public void testTransaction() throws Exception {
Connection conn = null;
//102向103转账100元
try{
conn = JDBCUtils.getConnection();
//关闭DML自动调教功能
conn.setAutoCommit(false);
String sql1 = "update user_tab set balance = balance - 100 where id = ?";
update(conn,sql1,102);
//模拟异常
System.out.println(10/0);
//103接受102转账100元
String sql2 = "update user_tab set balance = balance + 100 where id = ?";
update(conn,sql2,103);
//提交事务
conn.commit();
System.out.println("转账成功");
}catch (Exception e ){
e.printStackTrace();
//出现异常数据回滚
conn.rollback();
}finally {
//将自动提交功能设置还原为true
conn.setAutoCommit(true);
JDBCUtils.closeResource(conn,null);
}
}
a transferência falhou
(2) Simular a situação de transferência sem anormalidade
public void testTransaction() throws Exception {
Connection conn = null;
//102向103转账100元
try{
conn = JDBCUtils.getConnection();
//关闭DML自动调教功能
conn.setAutoCommit(false);
String sql1 = "update user_tab set balance = balance - 100 where id = ?";
update(conn,sql1,102);
//模拟异常
// System.out.println(10/0);
//103接受102转账100元
String sql2 = "update user_tab set balance = balance + 100 where id = ?";
update(conn,sql2,103);
//提交事务
conn.commit();
System.out.println("转账成功");
}catch (Exception e ){
e.printStackTrace();
//出现异常数据回滚
conn.rollback();
}finally {
//将自动提交功能设置还原为true
conn.setAutoCommit(true);
JDBCUtils.closeResource(conn,null);
}
}
transferência bem sucedida
4. Propriedades ACID das transações
(1) Atributos das transações
1. Atomicidade:
Atomicidade significa que uma transação é uma unidade de trabalho indivisível, e as operações na transação ocorrem todas ou nenhuma delas ocorre.
2. Consistência:
Uma transação deve fazer com que o banco de dados faça a transição de um estado consistente para outro estado consistente
3. Isolamento:
Quando as transações são executadas simultaneamente, os dados entre cada transação não interferem entre si e os dados entre cada transação não são afetados de forma alguma
4. Resistência:
Uma vez que uma transação é confirmada, é uma mudança permanente e nada do que acontece em seguida ou uma falha no banco de dados terá qualquer efeito sobre ela.
(2) Simultaneidade de transações
1. Leituras sujas:
Os dados não confirmados foram lidos .
Transação T1, transação T2, T1 lê um segmento de dados A e o valor lido é 1. Neste momento, T2 modifica o valor de A e T1 lê o valor de A = 2, mas neste momento, T2 cancela a transação e volta para o estágio A=1. Neste momento, os dados lidos por T1 são inválidos, o que é uma leitura suja:
2. Leitura não repetível:
Leia apenas os dados enviados, e o que for lido pela primeira vez, antes de enviar, o que for lido é o mesmo da primeira vez;
A transação T1 lê A=1 pela primeira vez.Após a leitura, não importa como outras transações (T2) atualizem e enviem o campo A (A=2), T1 sempre lerá A=1 antes de enviar;
3. Leitura fantasma:
A transação T1 lê 100 pedaços de dados pela primeira vez, e T2 insere 3 pedaços de dados e os envia.Após o envio T1, T1 os lê novamente e lê 103 pedaços de dados, que é uma leitura fantasma.
(3) Nível de isolamento
1. LEIA NÃO COMMITIDO (leia dados não confirmados)
2. READ COMMITED (ler dados confirmados)
3. LEITURA REPETIDA (leitura repetível)
4. Serialização: SERIALIZÁVEL (cada transação é executada sequencialmente)
(4) código .java para atingir o nível de isolamento ( framework deve ser usado, estabelecer as bases com antecedência )
package Transaction;
import UpAndSelMethod.Method;
import jdbcUtil.JDBCUtils;
import org.junit.Test;
import userBean.User;
import java.sql.Connection;
//*********卧槽,为啥我设置隔离级别为读未提交却读不出来修改了却为体骄傲的数据,麻了******************
public class Test隔离级别 {
//**************************测试事务并发问题与隔离级别的关系*********************************
//测试查询
@Test
public void testTransactionSelect() throws Exception {
Connection conn = JDBCUtils.getConnection();
//设置sql语句
String sql = "select id,name,balance from user_tab where id = ?";
//查看当前连接的的隔离级别
System.out.println(conn.getTransactionIsolation());
//设置当前连接的隔离级别为读未提交
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
System.out.println(conn.getTransactionIsolation());
User user = Method.selectinfo(User.class, sql, 103);
System.out.println(user);
}
//测试更新
@Test
public void testTransactionUpdate() throws Exception {
//获取连接
Connection conn = JDBCUtils.getConnection();
//设置自动提交为false
conn.setAutoCommit(false);
//sql
String sql = "update user_tab set balance = ? where id = ?";
//执行更新操作
Method.update(conn,sql,5000,103);
//线程睡眠15秒
Thread.sleep(15000);
//睡眠结束
System.out.println("修改完成");
}
}