事务
Transaction 一组操作包含多个单一操作,一组操作必须同事成功或者失败(回滚)
-- 显示是否自动提交(事务)
SHOW VARIABLES LIKE '%commit%'
-- 关闭自动提交
SET autocommit =off
-- 开启事务
START transaction
-- 回滚和提交
rollback commit
代码实例
代码的事务,主要是针对连接来的
1. 关闭自动提交
2. 开启事务
3. 提交
4. 异常回滚事务
@Test
public void testQuery() throws SQLException {
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
try {
//jdbc默认事务是自动提交的
conn = JDBCUtil.getConn();
//关闭自动提交
conn.setAutoCommit(false);
String sql="update student set age=age-? where sex=?";
ps = conn.prepareStatement(sql);
ps.setInt(1, 1);
ps.setInt(2, 31);
ps.executeUpdate();
ps.setInt(1, -1);
ps.setInt(2, 2);
ps.executeUpdate();
//提交事务
conn.commit();
} catch (SQLException e) {
e.printStackTrace();
//回滚事务
conn.rollback();
}finally {
JDBCUtil.release(conn, ps, rs);
}
}
ACID
- 原子性
事务中包含的逻辑不可分割
- 一致性
事务执行前后,数据完整性保持一致
- 隔离性
事务在执行期间,不应该受到其他事务的影响
- 持久性
事务执行成功,数据应该持久保存到磁盘上
隔离级别
- Read Uncommitted 读未提交
- Read Commited 读已提交
- Repeatable Read 重复读
- Senalizable 可串行化(事务排队,先开启事务的执行完毕,其他事务才能有动作)
- 设置隔离级别
set session transaction isolation level read uncommitted;
安全问题
- 读问题 :
- 脏读(读取的是内存中数据,而不是磁盘中数据,可通过读已提交隔离级别解决该问题)
- 不可重复读(在隔离级别是读已提交情况下,因为读取是已提交的,所以可能出现前后读取数据不一致,可能上一次读时候还没提交,
前端两次读取结果不同,这就是不可重复读,可以利用重复度隔离级别避免该问题) - 幻读(一个事务读到另一个事务已提交的插入的数据,导致查询结果不一致,通过可串行化解决,但是性能低)
- 写问题 : 丢失更新
解决方案
* 2.1 悲观锁(一定会丢失更新)
> 查询时候加上for update
悲观锁.png
* 2.2 乐观锁(一定不会丢失更新)
> 要求程序员自己控制,比如此时手动比较version,如果不符合version,则重新查询
乐观锁.png
-- 查询隔离级别(mysql默认是重复读)
SELECT @@tx_isolation;
网友评论