场景1:两个用户同时访问表,执行不同的操作:
上述如果用户A在用户B插入表之前读取表进行数据处理时,就会少读取新插入的数据,这就导致数据的不一致性。
所以,我们将采用锁的形式,在用户A读取表时,对表进行锁定。用户B等待用户A处理完成,对表解锁后,才可以进行插入数据操作。
锁的概念:
用户可以锁定一个对象,可以防止 其它用户修改锁定的对象
在多个用户并发访问数据库的情况下,为保证数据完整性,锁是很有必要的
程序可以显式的对数据枷锁,数据库系统可以隐式的对对象进行加锁
锁描述事务所操作对象的一种状态信息
一致性:一次只允许一个用户修改数据
完整性:为所有用户提供正确的数据。如果一个用户进行了修改并保存,所做的修改将反映给所有用户
锁类型:
- 共享锁(Shared locks):多个用户可以读取相同的记录 如果一个对象上没有排他锁,则共享锁可以加在该对象上,它可以防止其他事务更新数据,但同时,其他事务可以读取该数据,多个事务可以在同一个对象上加多个共享锁。
- 排他锁(Exclusive locks):同一时间仅仅有一个用户可以读取相同的记录 如果一个对象上没有任何锁,排他锁才可以加在该对象上。一旦在记录上加了排他锁,则不能在该记录上增加任何锁了,直至锁释放。它可以防止其他事务读取和更新数据。
- 提升/更新锁(Promotable/Update lock):可以对锁进行升级或者降级 在更新游标时使用,由游标在含有“for update”选项执行时产生,只能在没有排他锁或其他更新锁的记录上加更新锁。当锁定的记录真正执行的时候,更新锁将提升为排他锁。
- 专一锁(Intent lock):是一种表级锁,标识在该表上有一个游标在读取数据 由IDS自动分配,如果一条记录上的记录被更新,一个排他锁将分配在该记录上,同时将该记录的表上自动加上专一锁,这能保证没有session可以在该表上增加排他锁,只要该表中有记录被增加了排他锁。
锁粒度:
- 数据库级别锁(database-level locks):常用于数据库管理活动,例如improts和exports
- 表级锁(table-level locks):常用于当整个表或表的大部分数据需要更新,加表级锁效率高
- 页级锁(page locking):常用于当按数据物理顺序进行访问和更新时,页级锁效率高
- 行级锁(row locks):常用于在OLTP事务中采用行级锁,效率高
一般来讲,锁的粒度越大,并发性就越低,但是程序控制将越简单
查看表锁模式:
# oncheck -pt dbname:tablename
# dbschema -d dbname -t tablename -ss