如上,数据库在各种隔离级别下,SQL执行INSERT/UPDATE/DELETE语句时都会上X-LOCK,那么在读数据时如何上锁呢?
DB2和MySQL在Uncommitted Read隔离级别下,不加任何锁。
1)DB2
DB2在另外三种CS、RR、RS隔离级别时,SELECT语句,或CURSOR SELECT无UPDATE OF子句,FETCH时对读出的记录会上S-LOCK,不同的是,CS在读取下一行数据时就释放上一行的锁,RR、RS在事务提交时才释放锁;SELET…FOR UPDATE对读取的数据都是加U锁,CS在读取下一行数据时就释放上一行的锁,RR、RS在事务提交时才释放锁;INSERT/UPDATE/DELETE语句执行时会上X-LOCK,CS、RR、RS都是在事务提交时才释放X锁,其他事务不能对已锁定的行加任何锁。
2)MySQL
MySQL的InnoDB在隔离级别READ COMMITED 和 REPEATABLE READ(MySQL的默认隔离级别)下SELECT时不上锁,即MySQL中的一致性非锁定读;只有指定SELECT…LOCK IN SHARE MOAD才对记录上S-LOCK,SERIALIZABLE隔离级别下SELECT对记录上S-LOCK;三种隔离级别下,SELET…FOR UPDATE对读取的数据都是加X锁,在MySQL中叫做一致性锁定读。
3)Oracle
Oracle中只支持READ COMMITED和SERIALIZABLE隔离级别。这两种隔离级别下的锁机制和InnoDB一致。Oracle中不需要READ UNCOMMITTED隔离级别,是因为READ UNCOMMITTED主要功能是提高只读时的并发性,而Oracle在READ COMMITED隔离级别下使用一致性非锁定读也有同样的功能。
3、一致性非锁定读
隔离级别READ COMMITED 和 REPEATABLE READ(MySQL的默认隔离级别)都使用一致性非锁定读, SELECT时不上锁,那么如何保证事务的隔离性呢?这两种隔离级别采用快照数据的方式保证隔离性。读取时对于上了X锁的数据,都会去读取行的一个快照数据。快照数据是指该行的之前版本的数据,通过undo段实现。而undo段用来在事务中回滚数据,因此快照数据本身没有额外的开销。