标签:事务所 oracle 分割 之间 余额 永久 完整性 共享 lin
也可以使用命令去开启一个事务:
start transaction
:开启事务,这条语句之后的sql语句将处在一个事务当中,这些sql语句并不会立即执行Commit
:提交事务,一旦提交事务,事务中的所有sql语句才会执行。Rollback
:回滚事务,将之前所有的SQL取消。JDBC中管理事务:
conn.setAutoCommit(false);
conn.commit();
conn.rollback();
conn.setSavePoint();
conn.rollback(sp);
(所有的问题都是在某些情况下才会导致问题)
(一)、脏读:一个事务读取到了另一个事务未提交的数据。
#初始账户数据
a 1000
b 1000
----------
#a: 开启事务并进行对账户数据进行修改,但并没有提交
start transaction;
update account set money=money-100 where name=a;
update account set money=money+100 where name=b;
----------
#b: 开启事务查询账户
start transaction;
select * from account;
#查询结果如下:
a : 900
b : 1100
----------
#a: 这是回滚数据
rollback;
----------
#b:再此查询
start transaction;
select* from account;
#查询结果如下
a: 1000
b: 1000
(二)、不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同. --- 行级别的问题
a: 1000 1000 1000
b: 银行职员
---------
b:start transaction;
select 活期存款 from account where name='a'; ---- 活期存款:1000
select 定期存款 from account where name='a'; ---- 定期存款:1000
select 固定资产 from account where name='a'; ---- 固定资产:1000
-------
a:
start transaction;
update accounset set 活期=活期-1000 where name='a';
commit;
-------
select 活期+定期+固定 from account where name='a'; --- 总资产:2000
commit;
----------
(三)、幻读(虚读):一个事务读取到了另一个事务插入的数据(已提交),导致前后读取不一致 --- 表级别的问题
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;
------------
比较:
在MySQL中设置事务的隔离级别
MySQL
默认的数据库隔离级别为:REPEATABLE-READ
Oracle
默认下就是read committed
个隔离级别
如何查询当前数据库的隔离级别?
MySQL InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读)。我们可以通过SELECT @@tx_isolation
;命令来查看,MySQL 8.0 该命令改为SELECT @@transaction_isolation;
mysql> SELECT @@transaction_isolation;
+-------------------------+
| @@transaction_isolation |
+-------------------------+
| REPEATABLE-READ |
+-------------------------+
1 row in set (0.00 sec)
这里需要注意的是:与 SQL 标准不同的地方在于InnoDB 存储引擎在 REPEATABLE-READ(可重读)事务隔离级别下使用的是Next-Key Lock 锁算法,因此可以避免幻读的产生,这与其他数据库系统(如 SQL Server)是不同的。所以说InnoDB 存储引擎的默认支持的隔离级别是 REPEATABLE-READ(可重读) 已经可以完全保证事务的隔离性要求,即达到了 SQL标准的SERIALIZABLE(可串行化)隔离级别。
如何设置当前数据库的隔离级别?
SET [SESSION|GLOBAL] TRANSACTION ISOLATION LEVEL [READ UNCOMMITTED|READ COMMITTED|REPEATABLE READ|SERIALIZABLE]
此种方式设置的隔离级别只对当前连接起作用。
set transaction isolation level read uncommitted;
set session transaction isolation level read uncommitted;
此种方式设置的隔离级别是设置数据库默认的隔离级别
set global transaction isolation level read uncommitted;
排他锁:在所有隔离级别下进行增删改的操作都会加排他锁,
Serializable虽然可以防止更新丢失,但是效率太低,通常数据库不会用这个隔离级别,所以我们需要其他的机制来防止更新丢失:
两个线程基于同一个查询结果进行修改,后修改的人会将先修改人的修改覆盖掉.
乐观锁和悲观锁不是数据库中真正存在的锁,只是人们在解决更新丢失时的不同的解决方案,体现的是人们看待事务的态度。
悲观锁:
select * from xxx for update
乐观锁:
查询非常多,修改非常少,使用乐观锁
修改非常多,查询非常少,使用悲观锁
?
?
上面都讲过了,这里总结一下:
脏读(Dirty read): 当一个事务正在访问数据并且对数据进行了修改,而这种修改还没有提交到数据库中,这时另外一个事务也访问了这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据,那么另外一个事务读到的这个数据是“脏数据”,依据“脏数据”所做的操作可能是不正确的。
不可重复读(Unrepeatableread): 指在一个事务内多次读同一数据。在这个事务还没有结束时,另一个事务也访问该数据。那么,在第一个事务中的两次读数据之间,由于第二个事务的修改导致第一个事务两次读取的数据可能不太一样。这就发生了在一个事务内两次读到的数据是不一样的情况,因此称为不可重复读。
幻读(Phantom read): 幻读与不可重复读类似。它发生在一个事务(T1)读取了几行数据,接着另一个并发事务(T2)插入了一些数据时。在随后的查询中,第一个事务(T1)就会发现多了一些原本不存在的记录,就好像发生了幻觉一样,所以称为幻读。
丢失修改(Lost to modify): 指在一个事务读取一个数据时,另外一个事务也访问了该数据,那么在第一个事务中修改了这个数据后,第二个事务也修改了这个数据。这样第一个事务内的修改结果就被丢失,因此称为丢失修改。例如:事务1读取某表中的数据A=20,事务2也读取A=20,事务1修改A=A-1,事务2也修改A=A-1,最终结果A=19,事务1的修改被丢失。
标签:事务所 oracle 分割 之间 余额 永久 完整性 共享 lin
原文地址:https://www.cnblogs.com/haoworld/p/database-shi-wu.html