*1.事务概念_四大特性
create table account (
id int primary key auto_increment,
name varchar(20),
money double
);
insert into account values(null,'a',1000),(null,'b',1000);
一、事务
事务的概念:事务是指逻辑上的一组操作,这组操作要么同时完成要么同时不完成.
事务的管理:默认情况下,数据库会自动管理事务,管理的方式是一条语句就独占一个事务.
如果需要自己控制事务也可以通过如下命令开启/提交/回滚事务
start transaction;
commit;
rollback;
在jdbc中管理事务:
package com.itheima.transaction;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Savepoint;
import com.itheima.util.JDBCUtils;
public class JDBCTranDemo {
public static void main(String[] args) {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
Savepoint sp = null;
try{
conn = JDBCUtils.getConn();
conn.setAutoCommit(false);
ps = conn.prepareStatement("update account set money=money-100 where name = ?");
ps.setString(1, "a");
ps.executeUpdate();
ps = conn.prepareStatement("update account set money=money+100 where name=?");
ps.setString(1, "b");
ps.executeUpdate();
//设置回滚点
sp = conn.setSavepoint();
ps = conn.prepareStatement("update account set money=money-100 where name = ?");
ps.setString(1, "a");
ps.executeUpdate();
String str = null;
str.toUpperCase();
ps = conn.prepareStatement("update account set money=money+100 where name=?");
ps.setString(1, "b");
ps.executeUpdate();
conn.commit();
}catch (Exception e) {
try {
if(sp == null){//如果回滚点为null说明没有执行到设置回滚点代码时就抛了异常,应该所有语句进行回滚
conn.rollback();
}else{//说明sp不为null,可以会滚到回滚点,接着执行其他操作,但是要注意,如果希望之前的语句起作用,仍然需要做提交操作
conn.rollback(sp);
conn.commit();
}
} catch (SQLException e1) {
e1.printStackTrace();
}
e.printStackTrace();
}finally{
JDBCUtils.close(rs, ps, conn);
}
}
}
JDBC中管理事务:
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
SavePoint sp = conn.setSavePoint();
conn.rollback(sp);
事务的四大特性:一个事务具有的最基本的特性,一个设计良好的数据库可以帮我们保证事务具有这四大特性(ACID)
原子性:原子性是指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:如果事务执行之前数据库是一个完整性的状态,那么事务结束后,无论事务是否执行成功,数据库仍然是一个完整性状态.
数据库的完整性状态:当一个数据库中的所有的数据都符合数据库中所定义的所有的约束,此时可以称数据库是一个完整性状态.
隔离性:事务的隔离性是指多个用户并发访问数据库时,一个用户的事务不能被其它用户的事务所干扰,多个并发事务之间数据要相互隔离。
持久性:持久性是指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。
隔离性:
将数据库设计成单线程的数据库,可以防止所有的线程安全问题,自然就保证了隔离性.但是如果数据库设计成这样,那么效率就会极其低下.
*2.事务四大隔离级别
如果是两个线程并发修改,一定会互相捣乱,这时必须利用锁机制防止多个线程的并发修改
如果两个线程并发查询,没有线程安全问题
如果两个线程一个修改,一个查询......
第一个问题:
第二个问题:
虚读:
虚读(幻读):是指在一个事务内读取到了别的事务插入的数据,导致前后读取不一致 --- 表级别的问题
a: 1000
b: 1000
d: 银行业务人员
-----------
d:
start transaction;
select sum(money) from account; --- 2000 元
select count(name) from account; --- 2 个
------
c:
start transaction;
insert into account values(c,4000);
commit;
------
select sum(money)/count(name) from account; --- 平均:2000元/个
commit;
------------
四大隔离级别:
Read uncommitted -- 不防止任何隔离性问题,具有脏读/不可重复度/虚读(幻读)问题
Read committed -- 可以防止脏读问题,但是不能防止不可重复度/虚读(幻读)问题
Repeatable read -- 可以防止脏读/不可重复读问题,但是不能防止虚读(幻读)问题
Serializable -- 数据库被设计为单线程数据库,可以防止上述所有问题
从安全性上考虑: Serializable>Repeatable read>read committed>read uncommitted
从效率上考虑: read uncommitted>read committed>Repeatable read>Serializable
真正使用数据的时候,根据自己使用数据库的需求,综合分析对安全性和对效率的要求,选择一个隔离级别使数据库运行在这个隔离级别上.
mysql 默认下就是Repeatable read隔离级别
oracle 默认下就是read committed个隔离级别
查询当前数据库的隔离级别:select @@tx_isolation;
设置隔离级别:set [global/session] transaction isolation level xxxx;其中如果不写默认是session指的是修改当前客户端和数据库交互时的隔离级别,而如果使用golbal,则修改的是数据库的默认隔离级别
多练习这个锁机制!!!在dos界面!
*3.更新丢失_乐观锁_悲观锁
丢失更新!
更新丢失问题:
两个线程基于同一个查询结果进行修改,后修改的人会将先修改人的修改覆盖掉.
悲观锁:悲观锁悲观的认为每一次操作都会造成更新丢失问题,在每次查询时就加上排他锁
乐观锁:乐观锁会乐观的认为每次查询都不会造成更新丢失.利用一个版本字段进行控制
查询非常多,修改非常少,使用乐观锁
修改非常多,查询非常少,使用悲观锁