一个事务会涉及到大量的cpu计算和IO操作,这些操作被打包成一个执行单元,要么同时都完成,要么同时都不完成.
事务是一组原子性的sql命令或者说是一个独立的工作单元,如果数据库引擎能够成功的对数据库应用该组的全部sql语句,那么就执行该组命令
如果其中有任何一条语句因为崩溃或者其它原因无法执行,那么该组中所有的sql语句都不会执行
如果没有显式启动事务,数据库会根据autocommit的值.默认每条sql操作都会自动提交.
1.事务的四大特性(ACID)
原子性(Atomicity):一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部成功,要么全部失败回滚.对于一个事务而言,不可能只执行其中的一部分操作.
一致性(Consistency):事务开始前和结束后,数据的状态是保持正确的。比如A向B转账,不可能A扣了钱,B却没收到。
隔离性(Isolation):通常来说,一个事务所做的修改在最终提交之前,对其他事务是不可见的(为什么是通常,可以参考隔离级别)。比如A正在从一张银行卡中取钱,在A取钱的过程结束前,B不能向这张卡转账。
持久性(Durability):事务完成后,事务对数据库的所有更新将被保存到数据库,即使系统崩溃,修改的数据也不会丢失。
2.SQL-92标准规定的事务隔离级别(从低到高排序)
SQL事务具有ACID特性,但是事务并发可能导致脏读,不可重复读,幻读的问题.SQL标准规定了事务隔离级别用来解决事务并发问题.
read-uncommitted (读未提交):
在RU级别中,事务中的修改,即使没有提交,对其他事务也是可见的.如果其它事务回滚了操作,那么读到的就是脏数据.
read-committed (读已提交):
大多数数据库的默认隔离级别都是RC级别(Mysql例外),RC级别满足之前提到的隔离性,也就是一个事务开始时,只能读取到其它事务已经提交的修改,可能出现不可重复读.
(不可重复读的概念 : 事务A读取了数据,然后事务B在A多次读取数据的过程中修改并提交了数据,就会导致A读取到的数据结果不一致.)
repeatable-read (可重复读):
MYSQL默认的隔离级别.RR级别解决了脏读和不可重复读的问题,但是可能出现幻读
(幻读的概念 : 事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交。)
(注意 : Mysql Innodb引擎的实现跟SQL标准有不同.如果查询条件中使用唯一索引,或者唯一的查询条件,那么仅加行锁,如果是一个范围查询,那么就给这个范围加上next-key锁(行锁 + gap锁).因此在使用Innodb引擎时,在current read下可以避免幻读)
Serializable (串行化) :
最高的隔离级别.它通过强制事务串行执行,避免了之前所说的脏读,幻读,不可重复读问题.
简单来说,Serializable级别会在读取的每一行数据上都加上锁.所以可能导致大量超时和锁竞争的问题.实际应用中也很少用到这个隔离级别.只有在必须要确保数据一致性,且可以接受没有并发的情况下,才考虑用到该级别.
3.什么情况下会使用事务
使用 InnoDb引擎的情况下,默认SELECT,INSERT,UPDATE或DELETE都会开启事务。
在默认情况下,每个SQL都会被认为是一个事务且会自动提交.可以通过改变 autocommit 手动提交事务(只对当前connection有效).
4.死锁问题
死锁是指两个或者多个事务在同一资源上相互占用,并且请求对方锁定的资源,从而导致死循环的现象.为了解决这个问题,数据库系统实现了各种死锁检测和死锁超时机制.越复杂的系统,比如InnoDB引擎,越能检测死锁的循环依赖,并且立刻返回一个错误.这种解决方式很有效,否则死锁会导致出现非常慢的查询.
死锁发生以后,只有部分或者完全回滚其中一个事务,才能打破死锁.对于事务型的系统,死锁是无法避免的,所以在应用程序设计时必须考虑如何处理死锁.