1.事务概述
当多个用户访问同一份数据,一个用户在更改数据的过程中可能还有其他用户同时发起更改请求,为保证数据库记录的更新 从一个一致性状态变更为另外一个一致性状态,使用事务处理是非常必要的。事务具有以下4个特性
- 原子性
事务中的所有操作视为一个原子单位,即对与事务所进行的数据修改等操作这能是完全提交和完全回滚。
- 一致性
事务在完成时,必须使所有的数据从一种状态变更为另一种一致性状态,所有的变更都必须运用于事务的修改,以确保数据的完整性
- 隔离性
一个事务的操作语句所左的修改必须与其他事务所做的修改相隔离。在进行事务查看数据所处的状态,要么是被另一个事务修改之前的状态,要么是修改后的状态,即当前事务不会查看由另一个事务正在修改的数据。这种特性通过锁机制实现
- 持久性
事务完成之后,所做的修改对数据的影响是永久的,即使系统重启或者出现系统故障数据仍可以恢复。
2.事务的控制语句
在默认设置中,Mysql的事务是默认提交的。如需对某条语句进行事务控制,则使用start transaction或begin开始一个事务比较方便,这样事务结束后可以回到自动提交的方式。
3.数据库的并发问题
- 脏读:对于两个事务T1,T2,T1读取了被T2更新但没有提交的数据。之后若T2回滚,则T1读取的数据就是临时且无效的。
- 不可重复读:对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段,之后T1在一次读取同一个字段的值就不同了。
- 幻读:对于两个事务T1,T2,T1从一个表中读取了一个字段,然后T2在该表中插入了一些新的行,之后T1再次读取同一个表则会出多出现几行数据。
4.Mysql事务的隔离级别
- READ-UNCOMMITTED(读取未提交内容)
允许事务读取被其他事务锁更改的数据。脏读,不可重复读,幻读的问题均未解决。
创建相关表并插入演示所需数据
create table user_cursetom( id int(11) primary key auto_increment, balance double ); insert into user_cursetom(balance)values (1000), (1000);
设置该表的隔离级别为READ-UNCOMMOITTED
set global transaction isolation level read uncommitted;
在这需要注意的是需要退出当前连接重新连接数据库该设置才会有效。
select * from user_cursetom where id = 1;
事务A
begin; select id,balance from user_cursetom where id = 1;
事务B
begin; update user_cursetom set balance = 4000;
此时事务B并没有提交数据,而这时事务A查询的数据结果为
这时就出现了脏读的现象
- READ-COMMITTED(读取提交内容)
只允许事务读取其他事务所提交的更改
事务A
begin;
select id,balance from user_cursetom where id = 1;
事务B
begin;
update user_cursetom set balance = 4000;
此时事务B并没有提交数据,事务A的查询结果为
当事务B提交数据后,那么事务A再次的查询结果就不同了。
这就说明READ-COMMITTED并没有解决不可重复性读的问题
- REPEATABLE-READ(可重复读取)
确保事务可以多次的从一个字段中读取相同的值,在这个事务持续期间禁止其他事务对数据进行更改。可以解决脏读和不可重读问题。
事务A
begin;
select id,balance from user_cursetom where id = 1;
事务B
begin;
update user_cursetom set balance = 10000;
在事务B提交前,事务A的查询结果
在事务B提交数据后,事务A的查询结果都是一致的。这就说明了REPEATABLE READ解决的脏读和不可重复读的问题。
从结果可知,无论事务B是否提交,事务A的查询结果都是一zhi
- Serializable(可串行化)
确保事务可以从一个表中读取相同的行,在这个事务的执行期间禁止其他事务会数据进行更改。