事务是一种机制,一个操作序列,包含了一组数据库的操作命令,所有命令都是一个整体,向系统提交或者撤销的操作,要么都执行,要么都不执行。
A:原子性
最小单位,事务里的所有条件都是一个整体,不可分割。要么都成功,要么都失败。
案例: A给B转帐100元钱的时候只执行了扣款语句,就提交了,此时如果突然断电,A账号已经发生了扣款,B账号却没收到加款,在生活中就会引起纠纷。这种情况就需要事务的原子性来保证事务要么都执行,要么就都不执行。
C:一致性
事务开始之前和事务结束之后,数据库的完整性约束没有被破坏。
事务开始前,数据库中的存储数据要处于一致状态。
进行中的事务,数据可能处于不一致状态。
在事务最终完成时,数据必须再次回到已知的一致状态。
案例:对银行转帐事务,不管事务成功还是失败,应该保证事务结束后表中A和B的存款总额跟事务执行前一致。
I:隔离性
指在并发环境中,当不同事务同时操纵相同的数据时,每个事务都有各自的完整的数据空间。
对数据进行修改的所有并发事务是彼此隔离的,表名事务必须是独立的。
多个客户端并发地访问同一个表时,可能出现以下的一致性问题:
1、脏读:当一个事务正在访问数据,并且对数据进行了修改,
而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。
2、不可重复读:指在一个事务内,多次读同一数据。
在这个事务还没有结束时,另外一个事务也访问该同一数据。
那么,在第一个事务中的两次读数据之间,由于第二个事务的修改,
那么第一个事务两次读到的的数据可能是不一样的。
这样就发生了在一个事务内两次读到的数据是不一样的,因此称为是不可重复读。
(即不能读到相同的数据内容)
3、幻读:一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。
同时,另一个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。
那么,操作前一个事务的用户会发现表中还有没有修改的数据行,就好象发生了幻觉一样。
4、丢失更新:两个事务同时读取同一条记录,A先修改记录,B也修改记录(B不知道A修改过),
B提交数据后B的修改结果覆盖了A的修改结果。
如何避免?
1、权限控制
2、根据情况来使用隔离级别
生产环境--最好是提交读和可重读
测试环境--无所谓
3、生产环境只能允许一个人对一个事务
D:持久性
在事务完成以后,该事务所对数据库所作的更改便持久的保存在数据库之中,并不会被回滚。
指不管系统是否发生故障,事务处理的结果都是永久的。
一旦事务被提交,事务的效果会被永久地保留在数据库中。
总结:在事务管理中,原子性时基础,隔离性时手段,一致性是目的,持久性是最终结果
隔离级别 脏读取 不可重复读 幻像读
未提交读 允许 允许 允许
已提交读 禁止 允许 允许
可重复读 禁止 禁止 对InnoDB禁止
串行读 禁止 禁止 禁止
事务的隔离级别决定了事务之间可见的级别
1、未提交读,允许脏读,允许一个事务可以看到其他事务未提交的修改。
2、提交读,事务只能查看已经提交的修改,未提交的修改是不可见的,可以防止脏读。
3、可重复读,也是mysql的默认隔离级别,确保如果在一个事务中执行两次相同的select语句时,都能得到相同的结果 不管其他事务是否提交修改,可以防止脏读以及不可重复读。
(mysql默认的事务处理级别是repeatable read)
4、串行读,相当于锁表 完全串行化的读,将一个事务与其他事务完全地隔离,每次读都需要获得标记共享锁,读写相互都会阻塞。
show global variables like '%isolation%';
SELECT @@global.tx_isolation;
show session variables like '%isolation%';
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;
set global transaction isolation level read committed;
set @@global.tx_isolation='read-committed'; #重启服务后失效
set session transaction isolation level repeatable read;
set @@session.tx_isolation='repeatable-read';
BEGIN 或 START TRANSACTION:显式地开启一个事务。
COMMIT 或 COMMIT WORK:提交事务,并使已对数据库进行的所有修改变为永久性的。
ROLLBACK:回滚会结束用户的事务,并撤销正在进行的所有未提交的修改。
SAVEPOINT S1:使用 SAVEPOINT 允许在事务中创建一个回滚点,
一个事务中可以有多个 SAVEPOINT;“S1”代表回滚点名称。
ROLLBACK TO [SAVEPOINT] S1:把事务回滚到标记点。
SET AUTOCOMMIT=0; #禁止自动提交
SET AUTOCOMMIT=1; #开启自动提交,Mysql默认为1
SHOW VARIABLES LIKE 'AUTOCOMMIT'; #查看Mysql中的AUTOCOMMIT值
如果没有开启自动提交,当前会话连接的mysql的所有操作都会当成一个事务直到你输入rollback|commit当前事务才算结束。
当前事务结束前新的mysql连接时无法读取到任何当前会话的操作结果。
如果开起了自动提交,mysql会把每个sql语句当成一个事务,然后自动commit。
当然无论开启与否,begin; commit|rollback; 都是独立的事务。