事务是一组操作的集合,它是一个不可分割的工作单位,事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求,即这些操作要么同时成功,要么同时失败。
查看/设置事务提交方式
select @@autocommit; 输出为1 --自动提交,0--手动提交
set @@autocommit=0;
提交事务
commit;
回滚事务
rollback;
开启事务
start transaction 或 begin;
提交事务
commit;
回滚事务
rollback;
原子性(Atomicity):事务是不可分割的最小操作单元,要么全部成功,要么全部失败;
一致性(Consistency):事务完成时,必须使所有的数据都保持一致状态。
隔离性(Isolation):数据库系统提供的隔离机制,保证事务在不受外部并发操作影响的独立环境下运行。
持久性(Durability):事务一旦提交或回滚,它对数据库中的数据改变就是永久的。
-- 查看事务隔离级别
select @@transaction_isolation;
-- 设置事务隔离级别
set [session | global ] transaction isolation level [ read uncommitted | read committed | repeatavle read | serializable ]
注意:事务的隔离级别越高,性能越低。
打开两个命令符窗口
登录数据库 mysql -u root -p,切换到练习数据库use pra;
开启事务 start transaction
先查询一下表中数据 select * from account;
在第一个命令符窗口中设置事务隔离级别为read uncommitted——>set session transaction isolation level read uncommitted;
然后在第二个命令符窗口中输入命令:update account set money = money - 1000 where name = '张三'; 因为目前是开启的事务模式,所以不提交数据库是不会进行相关操作;但是在第一个命令符窗口中执行:select * from account; 会发现account表中的数据已经被修改,这就是脏读现象。
若在第一个命令符窗口中执行set session transaction isolation level read committed;即设置事务隔离级别为read committed,重复以上操作,则不会出现脏读现象。
设置read committed,解决脏读问题后,但是不能解决不可重复读现象。开启事务 start transaction(两个窗口),第一个窗口执行 select * from account; 然后第二窗口执行 update account set money = money + 1000 where name = '张三';,但是不执行提交,然后在第一个窗口再次执行 select * from account;发现两次查询结果一样,然后第二个窗口执行提交,第一个窗口执行查询,结果发现变化,这就是不可重复读。
将事务隔离级别设置为repeatable read,重复上述操作,可实现重复读取。
然而,repeatable read 隔离级别,无法解决幻读现象,开启事务 start transaction(两个窗口),第一个窗口执行select * from account where id = 3;返回空值,然后在第二个窗口执行 insert into account (id, name, money) values (3, '王五', 2000);,提交。再用第一个窗口查询,同样返回空值,然后再用第一个窗口执行插入命令 insert into account (id, name, money) values (3, '大刀王五', 2000); 返回error报错account中主键3重复,那么再次查询主键为3的数据,返回依然没有值。这种现象就是幻读。
幻读现象可以使用serializable(串行化)隔离级别解决。