SinoDB的锁机制

2022-03-17 00:00:00 数据 事务 排他 死锁 粒度

 在多用户数据库系统中,锁非常重要。用户可以锁定一个对象,可以防止其他用户修改锁定的对象。多个并发用户访问数据库数据的情况下,为了保证数据的完整性,锁是必需的。

一、什么是锁

       锁作为关联到数据项的对象。程序可以显示对数据加锁,数据库系统也可以隐式的对对象进行加锁。锁描述事务所操作对象的一种状态信息。

二、SinoDB的锁类型

SinoDB的锁类型有以下四种:

       Shared locks: 共享锁,多个用户可以同时读取相同的记录;

       Exclusive locks: 排他锁,同一时间仅仅有一个用户可以读取相同的记录;

       Promotable (Update) lock: 提升锁,可以从升级 (从共享锁提升为排他锁) 或者降级 (反之亦然);

       Intent lock: 专一锁,是一种表级锁,标识在该表上有一个游标在读取数据。

1.共享锁(lock-S)

      如果一个对象上没有排他锁,则共享锁可以加在该对象上,防止其他事务更新数据,但同时,其他事务可以读取该数据 (其他事务可以加共享锁),多个事务可以在同一个对象上加多个共享锁。

2.排他锁 (lock-X)

      如果记录上没有任何锁,排他锁才可以加在该对象上,一旦在记录上加了排他锁,则不能在该记录上增加任何锁了,直至锁释放防止其他事务读取和更修数据。

3.更新锁 (lock-U)

      更新锁由cursors 含有 ‘for update’ 选项执行时产生的 ,只能在没有排他锁或者更新锁的记录上加更新锁,当锁定的记录真正执行的时候,更新锁将提升为排他锁。


                        图12.2.2-3

4.专一锁 (lock-IX or IS)

       由SinoDB自动分配,如果一条记录上的记录被更新,一个排他锁将分配在该记录上,同时将该记录的表上自动加上专一锁,这能保证没有session可以在该表上增加排他锁,只要该表中有记录被增加了排他锁。

三、锁的有效期

       程序控制数据库锁的有效期:

       当SinoDB数据库关闭后,锁将被释放,根据数据库是否使用了事务的情况,表锁的有效期不同,如果数据没有使用事务(没有事务日志,也不使用commit work语句),显示对一个表lock,当执行unload table时,锁将被释放;当数据库使用了事务,事务结束时,将释放事务所有的锁 table, row, page, and index locks。

四、锁的粒度

1.在SinoDB数据库中, 我们可以按如下粒度进行加锁:

entire databases

数据库

entire tables

disk pages 

数据页

single rows, or index-key values

一般来讲,锁的粒度越大,并发性就越低,但是程序控制将越简单。


图12.2.4

2.什么情况下采用不同粒度的锁才有效、优?

1)Database-level locks:

数据库管理活动,比如: imports 和 exports,Ex: DATABASE database_name EXCLUSIVE

2)Table-level locks:

当整个表或者表的大部分数据需要更新,加表级锁效率高:LOCK TABLE tab1 IN EXCLUSIVE MODE,LOCK TABLE tab2 IN SHARE MODE,To unlock: UNLOCK TABLE tab1;

以下语句将隐式的对表加锁,直到事务结束后释放:

 ALTER FRAGMENT

 ALTER INDEX

 ALTER TABLE

 CREATE INDEX (if not using ONLINE keyword)

 DROP INDEX (if not using ONLINE keyword)

 RENAME COLUMN

 RENAME TABLE

3.不同粒度锁在何时确定?

页级锁:当按数据物理顺序进行访问和更新时,页级锁效率高,修改锁模式为页级锁:ALTER TABLE tab1 LOCK MODE PAGE;

PAGE锁模式是数据库默认的表锁模式,默认锁模式参数 (ONCONFIG) 文件参数 DEF_TABLE_LOCKMODE.

行级锁:OLTP 事务采用行级锁,效率高

Table must have lock mode ROW:

CREATE TABLE tab1  (col1...) LOCK MODE ROW;

ALTER TABLE tab1 LOCK MODE (ROW);

4、哪一种锁粒度是优的呢?

锁粒度取决于事务本身的特点,当更新表中相对较小一部分数据的时候,采用行级锁将获取好的性能无论如何, 数据库会发生锁益处的情况。如果一个事务只访问表中一小部分数据,那就采用行级锁。如果一个事务频繁的访问整个表的数据,设置更粗的粒度,比如表级锁。如果更新数据库中大部分表的大部分数据的情况下, 采用数据库级别的锁。

SinoDB默认的锁模式为页级锁 :

ALTER TABLE table_name LOCK MODE (ROW);

ONCONFIG 参数 DEF_TABLE_LOCKMODE设置默认锁模式

查看表锁模式

oncheck –pt dbname:tablename

dbschema –d dbname –t tablename -ss

五、设置锁模式

不等待锁的释放 (默认),如果数据库对象被锁,则立即返回错误,

Ex:-244: Could not do a physical-order read to fetch the next row

107:  ISAM error: record is locked

SET LOCK MODE TO NOT WAIT;

一直等待锁的释放,一个事务可能发生死锁和挂住,等待资源的释放SET LOCK MODE TO WAIT;在锁释放前,等待 n 秒直到等待N秒后,如果锁一直没有释放将返回锁等待超时错误信息,Ex: SET LOCK MODE TO WAIT 20;

六、死锁

当2个sessions加锁并且需要获取彼此之间的锁,将发生死锁

Example:

过程 A 等待过程B 释放资源

过程 B 等待过程A 释放其他的资源

过程A 等待 B ,而B又等待A …

死循环需要被中断

SinoDB 自动处理死锁:

在分配一个新锁前,SinoDB扫描内部的锁信息表,如果检测到死锁发生的条件,向应用程序发出ISAM error code 143。锁大等待时间通过ONCONFIG 参数 DEADLOCK_TIMEOUT设定。SinoDB使用DEADLOCK_TIMEOUT 作为来确定死锁的发生的一个条件。

 

图12.2.6

七、锁的监控与管理

监控session的隔离级别:

使用: onstat –g sql  或者  onstat –g ses

查看sid的详细信息: onstat –g sql sid

查看用户进程锁等待情况

使用: onstat –u

查看锁使用和等待情况:

使用: onstat -k

监控数据库事务及其状态:

使用: onstat -x

表被锁

ISAM error: key value locked

查询表的在数据库中的内部表号

select hex(partnum) from systables where tabname="test_lock";

返回值为:0x004000D4

查找上锁的用户线索

onstat -k|grep 4000D4 -i

45228970   0     985c8638    452288f0   HDR+IX   4000d4   0    0      

45228a70   0   985c8638   45228970   HDR+X  4000d4   101  0    U

查找用户线索对应的会话

onstat -u|grep 985c8638

address    flags   sessid   user     tty      wait    tout locks nreads   nwrites

985c8638   Y-BP--- 41   SinoDB -    9a2a0328    0  3    0      0

查看事务及锁的情况

onstat -x|grep 985c8638

找到相应的session 及SQL

onstat -g ses 41

杀掉session

onmode -z 41

相关文章