MySQL只有Innodb引擎支持数据库的事务操作。
MySQL事务保证了数据库的完整性,可以使得批量的SQL语句,要么全部执行,要么全部不执行。
一、MySQL事务有四大特性(ACID):
(一)原子性。(Atomicity)
事务的操作要么全部执行,要么全部不执行。若事务在操作的过程中发生什么错误,则事务将会回滚到事务开始前的状态,保证事务中的操作是不可分割的。
(二)一致性。(Consistency)
(三)隔离性。(Isolation)
(四)持久性。(Durability)
事务开始和完成前后,对数据库的操作是持久的。即使是系统故障也不会丢失。
二、事务并发会出现的问题
脏读:1.事务1读取数据A,并且更新数据A写回数据库;2.事务2读取新数据A;3.事务1进行回滚数据A变回旧数据A。这样事务2读取的数据和数据库真是数据是不一致的,发生了脏读。具体看下图:
事务1 | 事务2 |
第一步 .读取数据A=100; 更新数据A=A+20; 写进数据库A=120; | |
第二步.读取A=120; | |
第三步.RollBack A=100 |
事务1 | 事务2 |
第一步.读取A=100 | |
第二步.读取A=100; 更新数据A=A+20; 写回数据库A=120; | |
第三步.读取A=120 |
三、MySQL如何解决事务并发产生的问题
介绍前,首先需要介绍数据库的两种锁,排他锁(exclusive lock),也称为X锁,提供对数据更新和删除操作;共享锁(share lock),也称为s锁,提供对数据读操作。
1.共享锁(s锁):一旦事务1对记录上了s锁,则其他事务也允许对该记录上s锁,但是不能够再上x锁,事务读完后立即释放s锁。
2.排他锁(x锁):一旦事务1对记录上了x锁,只允许事务1对该记录更新和删除,其他事务不再允许对该记录上任何锁,只有等事务1释放了排他锁,其他事务才能够上锁。
(1) 避免‘脏’读数据:事务在读取记录的时候加上了共享锁(s锁),其他事务不允许在该记录上添加排他锁,不能够进行删除和更新操作,这样就避免了读‘脏’数据,但是避免不了不可重复读和幻读。
(2)避免不可重复读:任意事务读取数据的时候都添加共享锁(s锁),在事务结束后才释放锁。这样就避免了不可重复读和读‘脏’数据。
(3)避免幻读: 在实现上述(2)的基础上,共享锁和排他锁解决不了幻读的问题,因此加入了next-key locks,这个锁需要自己加,比如 事务1 select * from [table] where id > 1 for update,这样事务2若要添加 id 为2及以上的数据会添加不成功, 只有事务1结束了事务后,事务2才能够进行操作。这样避免了幻读,不可重复度,‘脏’读的问题。
四种隔离级别
事务级别 | ‘脏’读 | 不可重复读 | 幻读 |
读未提交(read-uncommitted) | 是 | 是 | 是 |
读已提交(read-committed) | 否 | 是 | 是 |
可重复度(repeatable-read) | 否 | 否 | 是 |
串行化(serializable) | 否 | 否 | 否 |