mysql的事务
一、事务的特性:ACID
1、原子性(atomicity):一个事务必须视为不可分割的最小单元,整个事务的所有操作要么全部提交,要么全部回滚 2、一致性(consistency):数据库总是从一个一致性状态转换到另外一个一致性状态。即事务没有提交,事务所做的修改不会保存到数据库当中 3、隔离性(isolation):通常来说(根据隔离级别而定),一个事务所做的修改在最终提交之前,对其他事物是不可见的。例如,事务A和B都是对某个字段进行修改,a修改的数据只要没有提交,在b看来数据是没有变化 4、可持久性(durability):一旦事务提交,则其所做的操作就会永久保存到数据库当中。
二、隔离性级别
1、未提交读(也叫脏读。read uncommited):事务即使没有提交,对其他事物也是可见的。事务可以读取未提交的数据。一般很少用到。 2、提交读(也叫不可重复读,red commited):大多数数据库的默认级别都是该隔离级别,但是mysql不是。该级别可以满足隔离性的要求,一个事务直到提交之前对其它事务是不可见的。 3、可重复读(repeatable read):mysql默认的隔离级别,可重复读解决了脏读的问题,该级别保证了同一事务中多次读取同样的结果记录是一致的。但是无法解决幻读(当某个事物读取范围内的记录时,另外一个事务在该范围内插入了一条记录,之前的事务读取就会出现幻行)的问题。innoDB和XtraDB的存储引擎通过多版本并发控制(MVCC)解决了该问题。 4、可串行化(serializable):该隔离级别是最高级别的隔离级别。它通过强制事务串行执行,避免了幻读的问题(加同步锁),在读取的每一行数据加上锁,所以可能会导致大量的超时和锁争用问题。
三、死锁
死锁是指两个或多个事务在同一资源上的相互占用,并请求锁定对方占用的资源,从而导致恶性循环。例如下,对表a进行一个数据的修改,当事务1没提交之前,修改了id为1并且锁定了记录,然后请求id为2的记录,事务2没提交前,修改了id为2并且锁定了记录,请求id为1的记录,两个事务互相等待造成了死锁。一般数据库对死锁会进行各种死锁检测和死锁超时机制。越是复杂的系统,如innoDB,越能检测到死锁的循环依赖,并且返回一个错误。innoDB目前处理死锁的方法是:将持有的最少行级的排它锁的事务回滚。
事务1
start transation
update a set a.name = 'a' where a.id = '1'
update a set a.name = 'b' where a.id = '2'
commit
事务2
start transation
update a set a.name = 'c' where a.id = '2'
update a set a.name = 'd' where a.id = '1 '
commit
四、事务日志
事务日志可以帮助提高事务的效率。数据引擎在修改表的数据时只需要修改其内存拷贝,再把该修改行为记录到持久在硬盘上的记录日志中,而不用每次将修改的数据本身持久到硬盘。事务日志持久后,内存中被修改的数据在后台可以慢慢刷回硬盘。这种情况称之为预写日志,修改数据需要写两次磁盘。 如果数据的修改已经记录到事务日志并持久化,但是数据本身没有写回磁盘,此时系统崩溃,存储引擎在重启时能够自动回复这部分修改的数据。
五、事务的自动提交
mysql默认的事务是自动提交的,如果需要修改。查询和执行如下(1和ON表示启用,0和OFF表示禁用):
show variables like 'autocommit';
set autocommit = '1';