事务并发带来的一些问题
(1)更新丢失(LostUpdate):当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题最后的更新覆盖了由其他事务所做的更新
(2)脏读(Dirty Reads):一个事务正在对一条记录做修改,在这个事务完成并且提交前,这条记录的数据就处于不一致状态;这时,另一个事务也来读取这一条记录,如果不加控制,第二个事务读取了这些脏数据,并据此做进一步的处理,就会产生未提交的数据依赖关系,这种形象的叫做脏读
(3)不可重复读(Non-Respeatable Reads):一个事务在读取某些数据后的某个时间,再次独缺以前读过的数据,却发现其读出的数据已经发生了改变或某些记录已经被删除了,这种现象就叫做不可重复读
(4)幻读(Phantom Reads):一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为幻读
一、InnoDB的行锁模式和加锁方法
表级锁:开销小,加锁快;不会出现死锁;锁粒度大,发生锁冲突的概率最高,并发度低
行级锁:开销大,加锁慢;会出现死锁;锁粒度最小,发生锁冲突的概率最低,并发度也最高
页面锁:开销和枷锁时间界于表锁和行锁之间;会出现死锁;锁粒度界于表锁和行锁之间,并发度一般
InnoDB支持表锁和行锁,默认情况下是采用行级锁
InnoDB实现了两种类型的行锁
1、共享锁(S):允许一个事物去读一行,阻止其他事物获得相同数据集的排他锁
2、排他锁(X):允许获得排他锁的事物更新数据,阻止其他事物取得相同数据集的共享读锁和排他写锁
换一种说法
共享锁【S锁】
又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。
排他锁【X锁】
又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。这保证了其他事务在T释放A上的锁之前不能再读取和修改A
为了允许行锁和表锁共存,实现多粒度锁机制,InnoDB还有两种内部使用的意向锁(Intention Locks),这两种意向锁都是表锁。
意向共享锁(IS):事务打算给数据行加行共享锁,事务在给一个数据行加共享锁前必须先取得该表的IS锁。
意向排他锁(IX):事务打算给数据行加行排他锁,事务在给一个数据行加排他锁前必须先取得该表的IX锁。
如果一个事物请求的锁模式和当前锁兼容,则InnoDB就将请求的锁授予该事物,反之如果两者不兼容,该事物就要等待锁释放。
意向锁是InnoDB自动加的,不需用户干预。对update、delete、insert语句,innoDB会自动给涉及数据集加排他锁;对于普通的select语句,InnoDB不会加任何锁;但是事物可以通过以下语句显示给记录集加共享锁和排他锁
显示共享锁
select * from brand where brand_code = '00AG' LOCK IN SHARE MODE