数据库-事务
2018-08-16 本文已影响0人
冰与河豚鱼
事务:是并发控制的基本单位,指作为单个逻辑工作单元执行的一系列操作,而这些逻辑工作单元需要满足ACID特性。
原子性:atomicity 事务是一个整体,要么全做,要么全不做
一致性:consistency
隔离性:isolation
持久性:durability
如果不开启事务,每条sql语句都会自动提交
事务中任何一条sql语句出错,事物都不会提交
MySQL默认事务隔离级别为repeatable read
事务隔离级别越高,数据库性能越差
JDBC事务控制:
Connection对象提供三个方法,实现一个事务逻辑
.setAutoCommit() 开启事务
.commit() 提交事务
.rollback() 回滚事务 虽然执行了的语句,回滚之后,回到事务之前的状态
public class TransactionTest(){
public static BasicDataSource ds = null;
static final String DRIVER_NAME = "com.mysql.jdbc.Driver";
static String DB_URL = "jdbc:mysql://localhost/test";
static final String USER_NAME = "root";
static final String PAEEWORD = "root";
public static void transferAccount() throws ClassNotFoundException{
Connection conn = null;
PreparedStatement ptmt = null;
try{
conn = ds.getConnection();
conn.setAutoComit(false);
ptmt = conn.prepareStatement("update user set account = ? where userName = ? ");
ptmt.setInt(1,0);
ptmt.setString(2,"zhangsan");
ptmt.execute();
ptmt.setInt(1,100);
ptmt.setString(2,"lisi");
ptmt.execute();
ptmt.commit();
}catch(SQLException e){
if(conn != null)
try{
conn.rollback();
}catch(SQLException e) {
e.printStackTrace();
}
}finally{
//关闭资源
}
}
}
检查点:
(待补充。。。)
脏读:读取一个事务未提交的更新
- 如何实现:
一:设置当前会话的隔离级别为read uncommitted
二:在其它会话里面开启事务,然后插入或者修改数据,但是不提交
三:在当前会话里面读取数据。-> 可以读到数据修改 - 如果避免:提高一个事务隔离级别 -> read committed以上
不可重读性:同一个事务中两次读取相同的记录,结果不一样
- 原因:读到了别人已提交的update数据
- 如何实现:
一:设置当前会话的事务隔离级别为read committed
二:在当前会话里面读取数据
三:在另外一个会话里面更新某条数据
四:在当前会话里面再次读取数据 - 如何避免:提高一个事务隔离级别 -> repeatable read以上
幻读:两次读取的结果包含的行记录不一样
- 如何实现:
一:设置当前会话的事务隔离级别为repeatable read
二:在当前会话里面读取数据
三:在另外一个会话里面插入或者删除数据
四:在当前会话里面再次读取数据 - 如何避免:设置隔离级别为repeatable read以上
事务隔离级别:
- Read uncommitted (读未提交) >>>脏读,不可重复读,幻读
- Read committed (读可提交) >>>不可重复读,幻读
- Repeatable read (可重复读) >>>幻读(mysql处理了该问题)
- Serializable (可串行化) >>>(并发访问性能大幅降低)
设置会话的事务隔离级别:
set session transaction isolation level read uncommitted;
select @@tx_isolation;
设置全局事务隔离级别:
set global transaction isolation level read committed;
select @@global.tx_isolation;