在我们区别InnoDB和MYISAM这两个存储引擎的时候,总会说一句前者支持行锁,然而这样的回答太笼统
数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性. 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大,会出现死锁。行级锁分为共享锁 和 排他锁。
两端锁
一段锁是在开始阶段申请所有的锁并锁住,等到结束后在释放锁这样可以避免死锁。而两端锁协议是将事务分为两个阶段,加锁阶段和解锁阶段:
加锁阶段:该阶段进行加锁操作,读数据申请S锁,写数据申请X锁,加锁失败则等待
解锁阶段:当事务释放了一个封锁以后,事务进入解锁阶段,在该阶段只能进行解锁操作不能再进行加锁操作
事务的隔离级别
未提交读(Read Uncommitted):允许脏读,也就是可能读取到其他会话中未提交事务修改的数据
可提交读(Read Committed):只能读取到已经提交的数据。Oracle等多数数据库默认都是该级别 (不重复读)
可重复读(Repeated Read):可重复读。在同一个事务内的查询都是事务开始时刻一致的,InnoDB默认级别。在SQL标准中,该隔离级别消除了不可重复读,但是还存在幻象读
串行读(Serializable):完全串行化的读,每次读都需要获得表级共享锁,读写相互都会阻塞
未提交读
对于未提交读,就是读写都不加锁,数据库不会用这种非常不安全的隔离级别,只有其会产生脏读(读到其他事物未提交的数据)。
事务在读数据的时候并未对数据加锁。
事务在修改数据的时候只对数据增加行级共享锁。
可提交读
在RC级别中,数据的读取都是不加锁的,但是数据的写入、修改和删除是需要加锁的。由于InnoDB是加行锁的,因此写入,修改和删除都会加行锁,这种说法并不可信,当再执行这些操作时,where中的如果是有索引的字段,则可以加行锁,如果没有索引,会加表锁,如果一个条件无法通过索引快速过滤,存储引擎层面就会将所有记录加锁后返回。因此我们更加体会到索引的作用,这里又可以有一个SQL优化经验,给经常修改,删除,删除的字段加上索引,能够有效的提高并发性
简单来说,可提交读就是当一个事务正在修改数据时,其他事务不能读,更不能改(即加入了X锁)
事务对当前被读取的数据加 行级共享锁(当读到时才加锁),一旦读完该行,立即释放该行级共享锁;
事务在更新某数据的瞬间(就是发生更新的瞬间),必须先对其加 行级排他锁,直到事务结束才释放。
这种隔离级别解决了脏读,但是会出现不可重复读。出现不可重复读的原因是事务1在整个事务