由于数据库要解决并发控制问题。在同一时刻,可能会有多个客户端对Table1.rown进行操做,好比有的在读取该行数据,其余的尝试去删除它。为了保证数据的一致性,数据库就要对这种并发操做进行控制,所以就有了锁的概念。数据库
读锁(共享锁):针对同一块数据,多个读操做能够同时进行而不会互相影响。架构
写锁(排他锁):当当前写操做没有完成前,它会阻断其余写锁和读锁。并发
表锁高并发
行锁性能
为了尽量提升数据库的并发度,每次锁定的数据范围越小越好,理论上每次只锁定当前操做的数据的方案会获得最大的并发度,可是管理锁是很耗资源的事情(涉及获取,检查,释放锁等动做),所以数据库系统须要在高并发响应和系统性能两方面进行平衡,这样就产生了“锁粒度(Lock granularity)”的概念spa
表锁:管理锁的开销最小,同时容许的并发量也最小的锁机制。MyIsam存储引擎使用的锁机制。当要写入数据时,把整个表都锁上,此时其余读、写动做一概等待。在MySql中,除了MyIsam存储引擎使用这种锁策略外,MySql自己也使用表锁来执行某些特定动做,好比alter table.orm
行锁:能够支持最大并发的锁策略。InnoDB和Falcon两张存储引擎都采用这种策略。排序
MySql是一种开放的架构,你能够实现本身的存储引擎,并实现本身的锁粒度策略,不像Oracle,你没有机会改变锁策略,Oracle采用的是行锁。事务
从业务角度出发,对数据库的一组操做要求保持4个特征:ci
Atomicity:原子性
Consistency:一致性,
Isolation:隔离性
Durability:持久性
为了更好地理解ACID,以银行帐户转帐为例:
1 START TRANSACTION;
2 SELECT balance FROM checking WHERE customer_id = 10233276;
3 UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;
4 UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;
5 COMMIT;
原子性:要么彻底提交(10233276的checking余额减小200,savings 的余额增长200),要么彻底回滚(两个表的余额都不发生变化)
一致性:这个例子的一致性体如今 200元不会由于数据库系统运行到第3行以后,第4行以前时崩溃而不知去向,由于事物尚未提交。
隔离性:容许在一个事务中的操做语句会与其余事务的语句隔离开,好比事务A运行到第3行以后,第4行以前,此时事务B去查询checking余额时,它仍然可以看到在事务A中被减去的200元,由于事务A和B是彼此隔离的。在事务A提交以前,事务B观察不到数据的改变。
持久性:这个很好理解。
事务跟锁同样都会须要大量工做,所以你能够根据你本身的须要来决定是否须要事务支持,从而选择不一样的存储引擎。
SQL标准定义了4类隔离级别,包括了一些具体规则,用来限定事务内外的哪些改变是可见的,哪些是不可见的。低级别的隔离级通常支持更高的并发处理,并拥有更低的系统开销。
Read Uncommitted(读取未提交内容)
在该隔离级别,全部事务均可以看到其余未提交事务的执行结果。本隔离级别不多用于实际应用,由于它的性能也不比其余级别好多少。读取未提交的数据,也被称之为脏读(Dirty Read)。
Read Committed(读取提交内容)
这是大多数数据库系统的默认隔离级别(但不是MySQL默认的)。它知足了隔离的简单定义:一个事务只能看见已经提交事务所作的改变。这种隔离级别 也支持所谓的不可重复读(Nonrepeatable Read),由于同一事务的其余实例在该实例处理其间可能会有新的commit,因此同一select可能返回不一样结果。
Repeatable Read(可重读)
这是MySQL的默认事务隔离级别,它确保同一事务的多个实例在并发读取数据时,会看到一样的数据行。不过理论上,这会致使另外一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另外一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎经过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。
Serializable(可串行化)
这是最高的隔离级别,它经过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每一个读的数据行上加上共享锁。在这个级别,可能致使大量的超时现象和锁竞争。
这四种隔离级别采起不一样的锁类型来实现,若读取的是同一个数据的话,就容易发生问题。例如:
脏读(Drity Read):某个事务已更新一份数据,另外一个事务在此时读取了同一份数据,因为某些缘由,前一个RollBack了操做,则后一个事务所读取的数据就会是不正确的。
不可重复读(Non-repeatable read):在一个事务的两次查询之中数据不一致,这多是两次查询过程当中间插入了一个事务更新的原有的数据。
幻读(Phantom Read):在一个事务的两次查询中数据笔数不一致,例若有一个事务查询了几列(Row)数据,而另外一个事务却在此时插入了新的几列数据,先前的事务在接下来的查询中,就会发现有几列数据是它先前所没有的。
在MySQL中,实现了这四种隔离级别,分别有可能产生问题以下所示: