数据库出现的并发读取错误:
脏读 :当一个事务对数据进行了修改时,但是修改还没有提交,这时,另外一个事务同时获取了已经被修改但未提交的数据;
幻读 : 幻读是指当事务不是独立执行时发生的一种现象,例如,事务A读取与搜索条件相匹配的若干行。事务B以插入或删除行等方式来修改事务A的结果集,然后再提交,那么,以后就会发生操作第一个事务的用户发现表中还存在没有修改的数据行,就好象发生了幻觉一样;
不可重复读 :一个事务内,多次读同一数据,在这个事务还没有结束时且在第一个事务中的两次读数据之间,另外一个事务也修改了同一数据,由于第二个事务的修改,那么第一个事务两次读到的的数据可能是不一样的。这样在一个事务内两次读到的数据是不一样的,因此称为是不可重复读;
数据库并发控制:
解决并发问题最有效的方案是引入了锁的机制,锁在功能上分为共享锁(shared lock)和排它锁(exclusive lock)即通常说的读写锁和互斥锁;
锁同样有粒度大小,有表级锁(table lock)和行级锁(row lock),分别在数据操作的过程中完成行的锁定和表的锁定。这些根据不同的存储引擎所具有的特性也是不一样的,MySQL大多数事务型的存储引擎都不是简单的行级锁,基于性能的考虑,他们一般都同时实现了多版本并发控制(MVCC);
innodb 引擎多版本并发控制实现
1) SELECT
对于select语句,只有同时满足了下面两个条件的行,才能被返回:
•行的被修改版本号小于或者等于该事务号
•行的被删除版本号要么没有被定义,要么大于事务的版本号:行的删除版本号如果没有被定义,说明该行没有被删除过;如果删除版本号大于当前事务的事务号,说明该行是被该事务后面启动的事务删除的,由于是repeatable read隔离等级,后开始的事务对数据的影响不应该被先开始的事务看见,所以该行应该被返回;
2) INSERT
对新插入的行,行的更新版本被修改为该事务的事务号;
3) DELETE
对于删除,innodb直接把该行的被删除版本号设置为当前的事务号,相当于标记为删除,而不是实际删除;
4) UPDATE
在更新行的时候,innodb会把原来的行复制一份到回滚段中,并把当前的事务号作为该行的更新版本;
MySql事务
事务就是一组原子性的SQL语句(要么不执行要么就全部执行(done or roll back));
特性:
1. 原子性(atomicity):事务中的所有操作要么全部提交成功,要么全部失败回滚;
2. 一致性(consistency):数据库总是从一个一致性状态转换到另一个一致性状态;
3. 隔离性(isolation):一个事务所做的修改在提交之前对其它事务是不可见的;
READ UNCOMMITTED(读未提交):事务中的修改即使未提交也是对其它事务可见;
READ COMMITTED(读提交):事务提交后所做的修改才会被另一个事务看见,可能产生一个事务中两次查询的结果不同;
REPEATABLE READ(可重读):只有当前事务提交才能看见另一个事务的修改结果。解决了一个事务中两次查询的结果不同的问题;
SERIALIZABLE(串行化):只有一个事务提交之后才会执行另一个事务;
4. 持久性(durability):一旦事务提交,其所做的修改便会永久保存在数据库中;
详细的实现原理可以参考《高性能MySQL》第三版;