mysql中只有innodb数据库引擎才支持事务,事务保证了数据库的数据完整性,同一个事务中的sql要么全部被执行,要么全部执行不成功。
事务四大特性:原子性,一致性,隔离性,持久性
原子性:
当前事务要么同时成功,要么同时失败,原子性通过undo log日志来保证的,undo log会记录这当前sql相反的执行语句,比如当前insert,在undo log 有对应的delete语句。确保执行失败能够恢复到执行前的数据状态。
隔离性:
多个事务间,操作同一条数据是隔离的,事务间不会相互干扰,避免脏读,不可重复读,幻读,事务提供了四种隔离级别:读未提交,读提交,可重复读,串行化,隔离级别越高性能越差,效果越好。mysql默认可重复读
隔离性是通过mysql的各种锁机制实现的。
持久性:
一旦事务提交了,将永久保存在磁盘中,通过redo log日志来保证。redo log按照顺序循环写,确保日志文件足够小,保证效率高,redo log 记录了某个数据页做了什么修改。
一致性:
通过其他三个特性,最终保证了数据的一致性,保证数据是我们想要的。
事务的隔离级别:
脏读:多事务间可以看到未保存到数据库的修改后数据,如果其中一个事务回滚,会造成数据混乱。
不可重复读:同一个事务同一sql查询前后执行两次,查询结果不相同。两次查询之间数据被修改。
幻读:两个事务同时修改一条数据,同时保存,数据被覆盖。造成其中一个事务感觉未修改。
测试方式:
1)将mysql自动提交事务关闭
--查看是否是自动提交 1表示开启,0表示关闭 select @@autocommit; set autocommit = 0;
2)测试数据
create database test; use test; create table test_trancation(id int primary key,name varchar(10))engine=innodb; insert into test_trancation values(1,'zhangsan'); insert into test_trancation values(2,'lisi'); insert into test_trancation values(3,'wangwu'); commit;
3)测试过程
测试1.脏读 read uncommitted
--打开两个窗口A,B,以下命令按顺序执行 A:set session transaction isolation level read uncommitted; B:set session transaction isolation level read uncommitted; A:select @@transaction_isolation; A:start transaction; A:select * from test_trancation; B:select * from test_trancation; A:update test_trancation set name ='12' where id =1; B:start transaction; A:select * from test_trancation; B:select * from test_trancation; A:commit; A:select * from test_trancation; B:select * from test_trancation;
测试2:不可重复读 read uncommitted
A:set session transaction isolation level read committed; B:set session transaction isolation level read uncommitted; A:select @@transaction_isolation; A:start transaction; A:select * from test_trancation; B:select * from test_trancation; A:update test_trancation set name ='32' where id =1; B:start transaction; A:select * from test_trancation; B:select * from test_trancation; A:commit; A:select * from test_trancation; B:select * from test_trancation;
测试3:幻读repeatable read
set session transaction isolation level repeatable read; A:start transaction; A:select * from test_trancation; B:start transaction; B:select * from test_trancation; A:insert into test_trancation values(4,'sisi'); A:commit; A:select * from test_trancation; B:select * from test_trancation; B:insert into test_trancation values(4,'sisi');--报错,无法插入数据