mysql事务
- 在 MySQL 中只有使用了 Innodb 数据库引擎才支持事务
- 事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
- 一般来说,事务需要满足4个条件(ACID):原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)
- mysql默认自动提交事务
原子性
一个事务(transaction)中的所有操作,要么全部完成,要么全部不完成,不会结束在中间某个环节。事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。
一致性
在事务开始之前和事务结束以后,数据库的完整性没有被破坏。这表示写入的资料必须完全符合所有的预设规则,这包含资料的精确度、串联性以及后续数据库可以自发性地完成预定的工作。
隔离性
数据库允许多个并发事务同时对其数据进行读写和修改的能力,隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
持久性
事务处理结束后,对数据的修改就是永久的,即便系统故障也不会丢失。
-
事务问题现象
InnoDB默认事务是可重复读级别的
脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
不可重复读:是指在事务A内,多次读同一数据。在这个事务A读取一次数据后,事务B也访问该同一数据并修改数据提交了事务,然后事务A再次去访问次数据发现两次数据不一致。这样就发生了在一个事务内两次读到的数据不一致,因此称为是不可重复读。
幻读:第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样,幻读是数据行记录变多了或者少了。
简单点总结下他们的区别:脏读是指读取了其他事务修改完未提交的记录,不可重复读指因为被其它事务修改了记录导致某事务两次读取记录不一致,而幻读是指因为其它事务对表做了增删导致某事务两次读取的表记录数不一致问题。
-
事务的隔离级别
隔离级别 | 脏读(Dirty Read) | 不可重复读(NonRepeatable Read) | 幻读(Phantom Read) |
---|---|---|---|
未提交读(Read uncommitted) | 可能 | 可能 | 可能 |
已提交读(Read committed) | 不可能 | 可能 | 可能 |
可重复读(Repeatable read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable ) | 不可能 | 不可能 | 不可能 |
read uncommitted 未提交读 所有事务都可以看到没有提交事务的数据。
eg: 公司发工资了,领导把5000元打到A的账号(正常工资2千)上,但是该事务并未提交,而A正好去查看账户,发现工资已经到账,是5000元整,非常高兴。但是领导随后发现给A的工资发多了,于是迅速回滚了事务,修改金额后,将事务提交,最后A实际的工资只有2000元,A空欢喜一场。
read committed 已提交读 事务成功提交后才可以被查询到。Oracle的默认隔离级别就是读已提交
eg: A拿着工资卡去消费,出门前查到卡里是2000元,凑巧紧接着她的老婆作为急用把A工资卡的2000元转到另一账户, 当A准备付款时,却发现工资卡已经没有钱,扣款失败......
repeatable 重复读 同一个事务内多次查询却返回了不同的数据值,即 可能将未提交的记录查询出来,而出现幻读。Mysql的默认隔离级别就是Repeatable read
前言:当隔离级别设置为Repeatable read 时,可以避免不可重复读。当A拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),A的老婆就不可能对该记录进行修改,也就是A的老婆不能在此时转账。 虽然Repeatable read避免了不可重复读,但还有可能出现幻读 。
eg1: A的老婆在银行工作,她可以很方便的查看A的信用卡消费记录。月末了,她正在查询A当月的消费情况 (select sum(amount) from transaction where month = ‘本月’)为80元,而A此时正好在某收银台买单,消费1000元,即新增了一条1000元的消费记录(insert transaction ... ),并提交了事务,随后A的老婆将A当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,A的老婆很诧异,以为出 现了幻觉,幻读就这样产生了。
Serializable可串行化 强制的进行排序,在每个读读数据行上添加共享锁。会导致大量超时现象和锁竞争。这是花费最高代价但是最可靠的事务隔离级别。
默认隔离级别
MySQL:
mysql默认的事务处理级别是'REPEATABLE-READ' -- 可重复读
1.查看当前会话隔离级别
select @@tx_isolation;
2.查看系统当前隔离级别
select @@global.tx_isolation;
3.设置当前会话隔离级别
set session transaction isolatin level repeatable read;
4.设置系统当前隔离级别
set global transaction isolation level repeatable read;
Oracle:
oracle数据库支持READ COMMITTED 和 SERIALIZABLE这两种事务隔离级别。
默认系统事务隔离级别是READ COMMITTED--- 读已提交
1.查看系统默认事务隔离级别,也是当前会话隔离级别
--首先创建一个事务
declare
trans_id Varchar2(100);
begin
trans_id := dbms_transaction.local_transaction_id( TRUE );
end;
--查看事务隔离级别
SELECT s.sid, s.serial#,
CASE BITAND(t.flag, POWER(2, 28))
WHEN 0 THEN 'READ COMMITTED'
ELSE 'SERIALIZABLE'
END AS isolation_level
FROM v$transaction t
JOIN v$session s ON t.addr = s.taddr AND s.sid = sys_context('USERENV', 'SID');
参考链接:
事务的隔离级别:https://www.cnblogs.com/shoshana-kong/p/10516404.html
事务的传播性:https://www.cnblogs.com/shoshana-kong/p/14020523.html