一、事务
1.事务的概念:事务指逻辑上的一组操作,组成这组操作的各个单元,要不全部成功,要不全部不成功。
例如:转账。如果不在一个事物中,出现异常产生的数据就会不正确。
二、MySQL数据库使用事务
1.在MySQL中使用命令
start transaction 开启事务
sql,,,
rollback 回滚事务
commit 提交事务
2.MySQL 数据库事务是默认提交的
show variables like ‘%commit%’; 查询是否默认提交
set autocommit = off或者0; 设置不默认提交。
如果设置autocommit 为 off,意味着以后每条SQL 都会处于一个事务中,相当于每条SQL执行前 都执行 start transaction。
3.MySQL使用事务
(1)方式一:
开启事物
start transaction;
update t_account set money = money - 1000 where username = 'aa';
update t_account set money = money + 1000 where username = 'bb';
提交或者回滚
commit; 或者 rollback;
(2)方式二
设置MySQL不让默认提交
set autocommit = 0或者off;
update t_account set money = money - 1000 where username = 'aa';
update t_account set money = money + 1000 where username = 'bb';
提交或者回滚
commit; 或者 rollback;
三、JDBC中使用事务
1.使用Connection接口操作事务
void setAutoCommit(boolean autoCommit) -- 设置默认不默认提交
void commit() -- 提交事物
void rollback() -- 回滚事物
2.保存点(了解)
(1)意义:有的时候一个复杂的事务可能由几个一致性的阶段组成,保存点就是在一个事务中,插入几个还原点,再出现问题时,可以及时撤回到这个地方。当撤回到一个还原点是,事务还在,仍在进行中,所以需要再次commit。这次的commit,保存点以下的执行相当于不存在。
(2)实现:
1.Savepoint sp = conn.setSavepoint();
2.conn.rollback(sp);
3.回滚到保存点的位置,事物没有结束,必须还要提交或者回滚事物才结束。
(3)参考链接:https://blog.csdn.net/buildingjiang/article/details/65442552
3.事务的特性
(1)原子性:事务是数据库的逻辑工作单位,事务中包含的事务要么都做,要么都不做。
(2)一致性:强调数据的完整性必须保持一致。事务执行的结果必须使数据库从一个一致性状态变为另一个一致性状态。如果数据库系统运行过程中发生故障,有些事务尚未完成就被迫中断,这些未完成事务对数据库所做的修改有一部分已经写入物理数据库,这时候数据库就处于一种不一致的状态。
(3)隔离性:一个事务的执行不能干扰其他事务。即一个事务内部的操作及使用的数据对其他并发事务是隔离的,并发执行的各个事务之间不能干扰。
(4)持续性:也成永久性,指事务一旦提交,它对数据中的数据的改变就应该是永久性的。接下来的操作不应该对其执行结果有任何影响。
4.不考虑隔离性会产生的一些问题
(1)脏读:事物A读取到了事物B未提交的数据
(2)不可重复读:事务A重新读取前面读取过的数据,发现该数据已经被另一个已提交的事务B修改过了。
(3)虚读(幻读):务A重新执行一个查询,返回一系列符合查询条件的行,发现其中插入了被事务B提交的行。
参考链接:https://www.liangzl.com/get-article-detail-15653.html
5.事务的隔离级别
隔离级别 |
脏读(Dirty Read) |
不可重复读(NonRepeatable Read) |
幻读(Phantom Read) |
未提交读(Read uncommitted) |
可能 |
可能 |
可能 |
已提交读(Read committed) |
不可能 |
可能 |
可能 |
可重复读(Repeatable read) |
不可能 |
不可能 |
可能 |
可串行化(Serializable ) |
不可能 |
不可能 |
不可能 |
安全性:read uncommitted < read committed < repeatable read < serializable
效率:read uncommitted > read committed > repeatable read > serializable
在数据库的设置隔离级别中,根据安全性和效率考虑,肯定不会用read uncommitted和serializable
在MySQL中默认的隔离级别:repeatable read
在Oracle中默认的隔离级别:read committed
6.MySQL中查询和设置隔离级别
查询数据库的隔离级别 select @@tx_isolation
设置数据库的隔离级别 set session transaction isolation level XXX; (XXX代表上述4种级别)
四、演示四种隔离级别
1.read uncommitted
.开启两个窗口A窗口和B窗口.分别登陆MySQL数据库
.设置隔离级别
set session transaction isolation level read uncommitted;
.在AB两个窗口中分别开启事物
start transaction;
.在B窗口中完成一些操作(转账的操作)
update t_account set money = money - 1000 where username = 'aa';
update t_account set money = money + 1000 where username = 'bb';
没有提交!!
.在A窗口做查询的操作
* select * from t_account;
.产生了脏读
2.read committed
.设置A窗口的隔离级别
set session transaction isolation level read committed;
.在AB两个窗口中分别开启事物
start transaction;
.在B窗口中完成一些操作(转账的操作)
update t_account set money = money - 1000 where username = 'aa';
update t_account set money = money + 1000 where username = 'bb';
.在A窗口中
select * from t_account;
.避免了脏读,产生了不可重复读
3.repeatable read
.设置A窗口的隔离级别
set session transaction isolation level repeatable read;
.在AB两个窗口中分别开启事物
start transaction;
.在B窗口中完成一些操作(转账的操作)
update t_account set money = money - 1000 where username = 'aa';
update t_account set money = money + 1000 where username = 'bb';
.在A窗口中
select * from t_account;
.在A窗口中,结束事物,在做查询
查询的结果是最新的结果
.总结:避免了脏读和不可重复读
4.serializable
.设置A窗口的隔离级别
set session transaction isolation level serializable;
.在AB两个窗口中分别开启事物
start transaction;
.在B窗口中添加一条数据
insert into t_account values (null,'cc',10000);
.在A窗口中做查询的操作
select * from t_account;
五、在JDBC中设置隔离级别
1.在Connection接口中提供了常量,这写常量分别代表不同的隔离级别
static int TRANSACTION_READ_UNCOMMITTED :指示可以发生脏读 (dirty read)、不可重复读和虚读 (phantom read) 的常量。
static int TRANSACTION_READ_COMMITTED :指示不可以发生脏读的常量;不可重复读和虚读可以发生。
static int TRANSACTION_REPEATABLE_READ :指示不可以发生脏读和不可重复读的常量;虚读可以发生。
static int TRANSACTION_SERIALIZABLE :指示不可以发生脏读、不可重复读和虚读的常量。
2.通过方法来进行设置,在Connection接口提供了一个方法
void setTransactionIsolation(int level)