监控数据库操作

1.监控数据库操作

  可监控的用户活动包括:

  • 每个会话的读取和写入
  • 持有锁的数量和类型
  • 最后一条 SQL 语句
  • 会话分配的线程数量
  • 会话创建的临时表大小
  • 会话运行的最大事务大小

  系统管理员可以监控单一用户会话的活动。以上列举了部分可监控的活动。通过这些信息,您可以确定应用程序代码中是否存在一个应由应用程序开发者来解决的问题。

2. 显示会话信息

$ onstat -g ses

session	#RSAM	total	used
id	userthread	tty	pid	hostname	threads	memory	memory
14	sinodbms	-	0	-	0	8192	4792
11	metcalf	ttypa	33436	orion	1	122880	102008
10	metcalf	ttyp9	33420	orion	1	131072	112464
9	metcalf	ttyp8	33404	orion	1	57344	48512
8	metcalf	ttyp7	33388	orion	1	57344	48512
7	metcalf	ttyp6	33372	orion	1	57344	44316
6	metcalf	ttyp1	33356	orion	1	73728	50052
5	metcalf	ttyp5	33353	orion	1	65536	48512
4	metcalf	ttyp4	33337	orion	1	73728	50580
3	metcalf	ttyp0	33321	orion	1	81920	50816
2	metcalf	ttyp3	33316	orion	1	90112	45372
1	metcalf	ttyp2	33310	orion	1	16384	12208

  如上述示例所示,如果包含一个会话 ID,onstat -g ses 命令可以列出关于该会话的更多特定信息。

  对于会话中的每个线程,展示以下信息:运行 onstat -g ses 命令可获取会话信息。这个功能对获取客户端应用程序信息十分有用,信息包括进程 ID、登录名和主机名。该项功能可获取以下会话信息:

字段 说明
session ID 会话的唯一 ID;该ID可用于其他 onstat 报表中
userthread 客户端应用程序进程的登录名
tty 客户端应用程序进程的 TTY 端口
pid 客户端应用程序进程的进程 ID
hostname 运行客户端应用程序进程的主机名
#RSAM threads 与会话相关的线程数量。通常情况下,每个会话只会分配一个线程,除非出现排序或索引。
Total memory 服务器共享内存中为会话分配的内存
usedmemory 服务器共享内存中会话已使用的内存

  sinodbms 拥有的且进程且ID 为 0 的会话不与用户对应。它们供数据库服务器内部使用。

3. 单一会话信息

$ onstat -g ses 251

Sinoregal SinoDB Dynamic Server Version 12.10.FC8 -- On-Line -- Up 22 days 22:29:20 -- 2765720 Kbytes

session           effective                            #RSAM    total      used       dynamic 
id       user     user      tty      pid      hostname threads  memory     memory     explain 
251      informix -         2        2587     vm84145  1        151552     121192     off 

Program :
/home/informix/sinodb/bin/dbaccess

tid      name     rstcb            flags    curstk   status
6170     sqlexec  476095a8         Y--P---  6448     cond wait  netnorm   -

Memory pools    count 2
name         class addr              totalsize  freesize   #allocfrag #freefrag 
251          V     48e06040         147456     29592      90         14        
251*O0       V     49f5b040         4096       768        1          1         

name           free       used           name           free       used      
overhead       0          6656           scb            0          144       
opentable      0          5952           filetable      0          1144      
log            0          16536          temprec        0          50336     
keys           0          224            gentcb         0          1640      
ostcb          0          2992           sort           0          104       
sqscb          0          22160          hashfiletab    0          552       
osenv          0          2752           sqtcb          0          9488      
fragman        0          368            sapi           0          144       

sqscb info
scb              sqscb            optofc   pdqpriority optcompind  directives
480a21c0         49b4c028         0        0           2           1         

Sess       SQL            Current            Iso Lock       SQL  ISAM F.E. 
Id         Stmt type      Database           Lvl Mode       ERR  ERR  Vers  Explain    
251        -              testdb3            CR  Not Wait   0    0    9.24  Off        

Last parsed SQL statement :
  select first 10 * from ods_fy_inheritor

  如上述示例所示,如果包含一个会话 ID,onstat -g ses 命令可以列出关于该会话的更多特定信息。
对于会话中的每个线程,展示以下信息:

字段 说明
tid 线程 ID
name 线程名
rstcb 线程的 RSAM 任务控制区(task control block)的地址
flags 线程的状态信息
status 该线程的当前状态

  一般情况下,对于每个会话您只能看到一个线程即sqlexec 线程。但是,排序或索引构建期间,可能会展示多个线程。

  onstat -g ses session-id 命令可列出更多信息,如下表所示:

字段 说明
Name, Free, Used 这几列显示了会话的资源池的准确使用情况
Sess Id 用户执行 SQL 语句的会话ID。您可以通过执行 onstat -g ses 命令查找相应的会话 ID 来查找用户名。
SQL Stmt type 语句类型,例如 SELECT、UPDATE、DELETE 或 INSERT
Current Database 会话的当前数据库的名称
Iso Lvl 当前隔离级别 (CR =committed read, RR =repeatable read, CS= cursor stability, DR = dirty read, NL = no logging)
Lock mode 当前锁模式 (Not WaitWait x , 其中x 为等待的秒数)
SQL ERR 最后一个 SQL 错误
ISAM ERR 最后一个 ISAM 错误
F.E.Vers 客户端应用程序的星瑞格数据库版本

临时表

  当前 SQL 语句及会话创建的任意临时表也会被列出。

4. SQL信息

$ onstat -g sql

Sinoregal SinoDB Dynamic Server Version 12.10.FC8 -- On-Line -- Up 22 days 22:42:43 -- 2765720 Kbytes


Sess       SQL            Current            Iso Lock       SQL  ISAM F.E. 
Id         Stmt type      Database           Lvl Mode       ERR  ERR  Vers  Explain    
251        -              testdb3            CR  Not Wait   0    0    9.24  Off        
29                        sysadmin           DR  Wait 5     0    0    -     Off        
28                        sysadmin           DR  Wait 5     0    0    -     Off        
27                        sysadmin           DR  Wait 5     0    0    -     Off        
26                        sysadmin           CR  Not Wait   0    0    -     Off   

  onstat -g sql 命令提供每个会话执行的最后一个SQL 语句的概述信息。onstat -g sql 命令运行结果中包含的字段如下:

字段 说明
Sess Id 用户执行 SQL 语句的会话 ID。您可以通过执行 onstat -g ses 命令查找相应的会话 ID 来查找用户名。
SQL Stmt type 语句类型,例如 SELECT、UPDATE、DELETE 或 INSERT
Current Database 会话的当前数据库的名称
Iso Lvl 当前隔离级别 (CR = committed read,RR = repeatable read, CS = cursor stability,DR = dirty read, NL =no logging)
Lock mode 当前锁模式 (Not WaitWait x , 其中x 为等待的秒数)
SQL ERR 最后一个 SQL 错误
ISAM ERR 最后一个 ISAM 错误
F.E.Version 客户端应用程序的星瑞格数据库版本

5. 监控准备就绪的SQL语句

$ onstat -g stm 29

Sinoregal SinoDB Dynamic Server Version 12.10.FC8 -- On-Line -- Up 22 days 22:53:31 -- 2765720 Kbytes

session 29         ---------------------------------------------------------------
sdblock          heapsz     statement ('*' = Open cursor)
48d63028         4960        -
48d632d8         16816       INSERT INTO ph_run  ( run_id, run_task_id, run_task_seq, run_retcode,    run_duration, run_ztime, run_btime, run_mttime )  VALUES ( 0, ?, ?, ?, ?, ?, ?, ? )
48d63588         80640       SELECT MAX(run_task_seq) FROM ph_run A, ph_task B WHERE A.run_task_id = ? AND A.run_task_id = B.tk_id AND A.run_time + B.tk_delete < CURRENT
48d63838         18632       DELETE FROM ph_run WHERE run_task_id = ? AND run_task_seq <= ?
48d63ae8         78680       UPDATE ph_task  SET (  tk_next_execution,  tk_total_executions,  tk_total_time, tk_attributes  ) = ( ?, tk_total_executions + ?,  tk_total_time + ?,  BITANDNOT(tk_attributes, 514 )  )  WHERE tk_id = ? 

  SinoDB数据库应用程序开发工具,例如 ESQL/C, 允许语句只在应用程序中准备就绪一次,就可以在不需要重新解析或重新优化情况下再次使用。这些准备就绪的语句保存在应用程序的会话控制区(session control block),直到会话结束才会被释放。您可以通过执行下面这条命令查看任一会话已准备就绪的语句列表:

onstat -g stm sessid

sessid 是会话 ID 。以上是运行该命令的输出示例。

6. 监控用户线程

$ onstat -u
address	flags	sessid	user	tty	wait	tout	locks	nreads	nwrites
a120018	---P--D	1	sinodbms	-	0	0	0	50	33
a1204bc	---P--F	0	sinodbms	-	0	0	0	0	278
a120e04	---P--B	7	sinodbms	-	0	0	0	1	0
a1212a8	---P--D	9	sinodbms	-	0	0	0	0	0
a12174c	L--PR--	26	joeg	ttyp2	a01f8d4	-1	1	0	0
a121bf0	Y-BP---	23	lizg	ttyp1	2fb050	0	6	0	0

$ onstat -k
address	wtlist	owner	lklist	type	tblsnum	rowid	key#/bsiz
a01f838	0	a121bf0	0	HDR+S	100002	205	0
a01f86c	0	a121bf0	a01f838	HDR+IX	100085	0	0
a01f8d4	a12174c	a121bf0	a01fa40	HDR+X	100085	400	0
a01f908	0	a121bf0	a01f970	HDR+X	100085	200	2
a01f970	0	a121bf0	a01f86c	HDR+X	100085	100	1
a01fa40	0	a121bf0	a01f908	HDR+X	100085	300	3
a01fbe0	0	a12174c	0	S	100002	205	0

  以上一个是锁信息 (onstat -k )示例,展示了用户joeg 在等待用户lizg 占用的锁。用户 lizg 在等待一个条件,这可能意味着线程空闲且正在等待一条来自应用程序的 SQL 语句。onstat -u 命令列出了需要一个RSAM 任务控制区 (rstcb ) 结构体的所有线程。它包括了会话的所有线程,加上一些服务器维护线程,例如页面清理线程、 mainloop 线程、B树清理线程和恢复线程。

  onstat -u 命令很重要,因为它可以帮助确定会话状态或它的一个线程的状态。例如,您可以查看一个会话是否在等待锁、回滚事务或等待检查点完成。

  如果有地址被列在 wait 列上,那么该线程在等待特定的条目。条目类型可以由 flags 列的第一个位置中的标识确定。对于很多线程而言,有地址在 wait 列上是很常见的;例如,它在等待一个条件。

  想要查看更多关于会话的信息,指定一个会话 ID 并运行onstat -g ses session-id 命令。

  flags 列列出了线程的状态。在 flags 列中标识的位置对于识别标识所代表的意义很重要。下一页展示了标识位置以及在每个位置中可以使用的标识的列表。

7. 使用SMI监控会话

SELECT * FROM syssesprof;

sid                29
lockreqs           10659748
locksheld          1
lockwts            0
deadlks            0
lktouts            0
logrecs            667137
isreads            3815001
iswrites           168480
isrewrites         2160
isdeletes          118910
iscommits          10510
isrollbacks        0
longtxs            0
bufreads           9312863
bufwrites          1027851
seqscans           51018
pagreads           4122
pagwrites          43258
total_sorts        423
dsksorts           0
max_sortdiskspace  0
logspused          472
maxlogsp           511272

  可以通过SMI 表、syssesprofsyssessions 获取与onstat 命令相同的用户信息。以上展示了基于syssesprof 表的查询结果示例。

> SELECT * FROM syssessions;



sid         27
username    informix
uid         1001
pid         0
hostname    
tty         
connected   1700469017
feprogram   
pooladdr    1224687680
is_wlatch   0
is_wlock    0
is_wbuff    0
is_wckpt    0
is_wlogbuf  0
is_wtrans   0
is_monitor  0
is_incrit   0
state       524289

  以上展示了基于syssessions 表的查询结果示例。该查询展示了一些与执行onstat -g ses 命令可获取到的相同信息。

8. 监控事务大小

SELECT longtxs, logspused, maxlogsp  
 FROM syssesprof WHERE sid = 27;   

   longtxs     0          # 长事务
   logspused   0    # 由当前事务使用的日志空间(以字节为单位)
   maxlogsp    9824 # 在当前会话中,由事务使用的最大日志空间(单位:字节)

  想要找出会话使用的逻辑日志空间的数量,您可以从syssesprof 表中查询,或者运行onstat -g tpf session-id 命令。该信息对验证逻辑日志的大小和数量是否足以处理由会话运行的事务而言很重要。

  切记只要客户端应用程序连接服务器,syssesprof 中的条目就会保留。

9. 移除问题会话

  如果您想移除会话:

  • 如果可能请正常的结束应用程序进程
  • 杀死应用程序进程
  • 会话应该检测应用程序进程连接断开。如果检测不到,运行:
   onmode -z sess-id

  您可能会因为某些原因想要中止会话,例如死锁、长事务或用户占用了需要的资源。在这种情况下,尽可能正常的退出应用程序(或让用户这么做)。

  如果无法正常退出,那么杀死应用程序进程。会话应该检测应用程序进程连接断开。如果 onstat -g ses 显示会话一直存在,那么请运行onmode -z sess-id 。例如:

   onmode -z 23

10. 识别资源不足

  在某些情况下,初始配置不足以处理在数据库服务器上的运行的命令。系统管理员可以使用 onstat -p 命令监控可用资源是否充足。该配置文件 信息包含三个字段,表示系统资源的请求是否已超过资源供给。这些字段如下:

  • ovlock ——该字段如果是一个非零值则表示分配的锁的数量不足。在这种情况下,请增加 LOCKS 的值。
  • ovuserthread —— 该字段如果是一个非零值则表示分配的用户线程的数量不足。
  • ovbuf —— 该字段如果是一个非零值则表示分配的缓冲区的数量不足。增加 BUFFERS 的数量可以提高性能。

  这些字段偶然性的出现非零值不一定就意味着必须重新调整系统。如果这些字段的值有规律地增加,那么就要考虑重新调整系统。

11. 识别锁争用


  onstat -p 命令输出结果中的lockwaitslockreqs 列可用于识别可能的锁争用(lock contention)。必须等待的锁请求的机率极小。如果等待的机率较高,您应该检查下列区域:

  • 页级锁——可能是由于太多页级锁造成等待。在这种情况下,请考虑使用行级锁。
  • 表级锁——审查使用表级锁的应用程序,判定是否应该由其他锁替代。
  • 应用程序隔离级别——检查隔离级别被设置为repeatable read和cursor stability区域。确定dirty read隔离级别是否可以更频繁的使用。

12. 死锁超时

  当进程等待远程系统的一个响应的时间已达到指定的值时,网络死锁超时将出现。如果超过等待时间,本地服务器会认为已出现网络死锁,并返回错误至应用程序。无论何时发生,dltouts 字段都会增加。

  很可能远程服务器系统网络缓慢或响应时间过长,超时并不是因为网络死锁,而是因为响应时间过长。在这种情况下,您可以尝试通过增加等待时间来减少超时发生的机率。可以通过修改配置文件里 DEADLOCK_TIMEOUT 参数的值来完成。该参数的值单位为秒,其缺省值是 60。

  增加 DEADLOCK_TIMEOUT 的值将允许进程使用更长的时间来等待远程站点的响应,从而减少网络死锁数。但是也可能会造成在用户看来更差的性能,因为更长的等待时间意味着用户需要更长的时间才能得到响应。

  或者,也可以减少 DEADLOCK_TIMEOUT 的值,即应该增加dltouts 数,但用户可能会更快的获得响应(以错误的形式)。

死锁
  进程 B 占用着进程A 需要的数据,且进程 A 也占用着进程B 需要的数据,此时会发生死锁。服务器通过回滚进程并返回错误的方式防止死锁出现。当一个死锁被检测到且回滚时,deadlks 的值增加 1 。

  如果您观察到 deadlks 的值显著增加,请检查应用程序中可能发生死锁的场景。

13. 监控锁使用

  • 使用 onstat -k 命令监控数据库服务器中的锁。

  • 获取锁的历史数据:onstat -rk >filename .

  • 造成性能问题的锁类型:
    — 排他数据库锁(exclusive database locks)
    — 排他表锁(exclusive table locks)
    — 页级锁(page-level locks)

  • 使用 ALTER TABLE 命令把页级锁更改为行级锁。

  • 通过更改应用程序清除导致性能问题的排他数据库和表锁。

  系统管理员应该监控服务器中的锁使用,尤其是当应用程序出现响应时间的问题时。

  onstat -k 命令展示了服务器中当前占用的所有锁。您可以构建一个文件,包含某段时间内锁的使用历史。

  性能问题最常见的原因是使用了粒度过大的锁。为了更好地识别锁的类型和它们的粒度,以下几页展示了onstat -k 输出样本以及识别锁类型的方法。

13.1 监控锁类型

  SinoDB 数据库通过使用锁强制更新读取 并发控制。有四种锁类型:

  • 共享锁 (shared locks) 用于管理读取并发。它们允许所有用户都可以读取被锁定的资源,但是不能更新资源。多重共享锁可被置于同一资源上。共享锁可被置于数据库、表、页、行或键级上。在表的行上放置一个共享锁实际上会导致几个共享锁被放置:一个置于数据库上的共享锁(数据库打开时总是出现),一个置于表上的意图 共享锁和一个置于行上的共享锁。

  • 排他锁 ( exclusive locks ) 用于管理更新并发。它们阻止用户以任何方式访问锁定的资源。用户必须获取一个排他锁且资源上不存在其他锁才能更新资源。占有一个或多个页或行级上的排他 锁的用户也可以有一个表级上的意图 排他锁。

  • 更新锁 ( update locks ) 用于在使用更新游标时管理更新并发。它与可被提升为排他锁的共享锁类似。在提取操作期间,放置更新锁,然后在更新语句执行期间提升为排他锁。更新锁及其导致的提升的排他锁,除了数据库上的共享锁外,还一个共享意向排他表锁与之相关联。

  • 意向锁 ( intent locks ) 是与更高的粒度锁(页或行)相关联的表级锁。每张表上单一的意向锁与页和行级锁一起出现。确保了在页或行级上的操作的表级完整性。注意意向锁并没有与常规表锁相同的并发。因此,两个用户很可能在同一张表上占用意向排他锁。以下是意向锁的三个类型:
    — 连同行和页级的共享锁,放置意向共享锁。
    — 当进程同时拥有行和页级的共享和排他锁时,放置共享意向排他锁。
    — 连同行和页级的排他锁,放置意向排他锁。

13.2 repeatable read 隔离级别下的锁类型

  服务器系统使用特殊的锁来管理repeatable read隔离级别。

  • 运行repeatable read的 SELECT 语句在它检查的每一行上都放置一个 SR 锁,以满足查询。
  • DELETE 语句在它删除的每个键上放置一个 XR 锁。
  • INSERT 语句在当前键条目上放置一个 XR 锁,并检查相邻键上锁。

13.3 锁的粒度

  SinoDB数据库有以下不同的锁粒度,数据库服务器可以在不同大小或粒度的对象上放置锁:

  • 数据库锁——在整个数据库上的锁
  • 表锁——在整张表上的锁
  • 页锁——在整个数据页上的锁
  • 行锁——在单一数据行上的锁
  • 字节锁——在包含 VARCHARs 的行上的锁
  • 键锁——在索引里单一键值上的锁

  SinoDB数据库服务器使用基于对象大小或粒度( granularity 的各种方式锁定对象。锁粒度从最大的数据库级 锁到最细的行级 锁。由任何数据库事务使用的粒度取决于应用程序开发者选择的访问方式,外加建表时 DBA 做出的某些决定。

  在服务器锁管理器 中有两个组件用于锁识别:tblspace 编号用于识别与锁相关联的表;rowid 用于识别被锁定的表内的元素。该信息也用于确定锁的粒度。

13.3.1 数据库锁

  SinoDB数据库服务器的数据库锁并不特殊。但是了解一些关于服务器的内部结构的知识有助于您识别数据库上的锁。

  如前一个模块所述,特殊的 tblspace为追踪在服务器系统中创建的数据库而保留。它总是root dbspace 中的第二个 tblspace (tblsnum = 0x100002 )。这个tblspace 中的每一行都包含关于服务器中的每个数据库的信息。

  数据库请求锁时,实际是把锁放置在database tblspace 中 上。如果数据库被排他锁锁定,如上所示,那么将在该行上放置排他锁。任何数据库的非排他访问都会导致在该行上放置共享锁。因此,只要数据库打开,就会在该行上维护一个锁。如果几个用户同时访问该数据库,那么该行可以有几个共享锁。因为排他锁拒绝任何其他人访问数据库,因此该行上只会有一个排他锁。

  尽管没有将database tblspace 中行的 rowid 映射到特定的数据库名的工具,但确实存在一种关系。创建的第一个数据库有最小的 rowid,且在服务器中每创建一个数据库,rowid就会递增。如果记录了数据库创建的顺序,您可以关联数据库和 rowid。

13.3.2 表锁

  数据库级锁粒度的下一级是表级锁 。它锁定表中所有数据。您既可以在共享模式下锁定一个表,此时只允许其他用户读取表中的数据;也可在独占模式下锁定表,此时不允许其他用户对锁定的表进行任何访问操作。

  如果一个用户持有某张表的排它锁,那么无论该用户对此表进行多少更改,都不再需要更多的锁。如果一个用户持有某张表的共享锁,那么无论对此表进行何种更改,也需对想要更改的数据添加低一级的锁。

  表是否被锁定很容易被识别,只需查看 onstat -k 命令的报表中rowid 列是否为0,若为0即表示被锁定。tblsnum 值与分区编号 (partnum) 对应。要查看数据库中的表以及表的 tblsnum 值,请运行:

  SELECT tabname, hex(partnum) FROM systables ORDER BY 2

  表级锁的rowid 值总是为 0,因为页号和槽号(slot number)都不与表相关联。

  由于多个用户可以获取同一张表的共享锁,因此同一张表上可以存在多个共享锁。但这不适用于排它锁;一张表在同一时间最多只能有一个排它锁。通常,表级锁由程序员显示进行设置。意向锁是另一种表锁,与其他锁一起隐式的设置。后面会介绍这种锁。

13.3.3 页锁

  创建表时,您可以指定希望使用页级锁还是行级锁的方式来锁定此表。表中所有元素的锁定都根据创建该表时所指定的锁级别。当选择使用页级锁 时,无论该页包含多少行,整个页中的数据都将被锁定。

  如果一页包含五行数据,而其中四行在某一事务中需要被锁定,那么页级锁最高效(相比于四个行级锁)。但是,如果五行数据中只有一行需要被锁定,页级锁会妨碍对该页中其余四行的访问。页级锁定通常需要更少开销,但代价是会减少并发。

onstat -k 命令的报表中很容易识别是否包含页级锁,只需查看 rowid 值是否不包含槽号组件(槽号指的是页中的具体行),因此 rowid 值总是以 00 结尾。

13.3.4 行锁

  创建表时,您可以指定希望使用页级锁还是行级锁的方式来锁定此表。所有对该表的锁定(表级以下的锁)都根据创建表时所指定的锁模式。当选择使用行锁 时,只对更新过的行进行锁定。

  行级锁为表的并发提供的最大可能。但这种高并发的代价是需要大量的锁。

  行级锁在 onstat -k 报表中很容易被识别出来,只需查看锁的 rowid 是否不是以 00 结尾。

13.3.5 键锁

  每当表中某一行的更新涉及到更改该行中的一个或多个键值时,该表将增加一个或多个键锁。键锁应用于更新的行对应的索引条目。

  例如,如果您删除了包含唯一索引的表中的某一行,则不仅会对该行进行锁定,还会对键进行锁定。这可以保证在事务周期中索引的完整性。

  当使用repeatable read的隔离级别,且使用索引访问某行时,一个共享锁会应用在所有被访问的键值上。这是在键值上应用共享锁的唯一场景。通常情况下,应用在键值上的锁都是排它锁,且与插入、更新或删除操作相关。

13.3.6 字节锁

  当事务使用的表包含可变长列 (varchar)时 ,有必要对行的某些字节进行锁定(由于行的大小可能会在修改期间发生变化)。这种情况下,会用到字节锁 。字节锁只锁定被修改的行中的某些字节。实际被锁定的字节大小可在 onstat-k 命令的报表中的 bsiz 列中查看。字节锁的 rowid 值与被锁定的数据所在页对应,因此以 00 结尾。

  将type 字段中的B 值与size 字段中的非零值结合起来看,可以很容易的识别字节锁。如果被修改的表使用了页级锁,字节锁可以合并到页中现有的锁中。这种情况下,锁类型为 X,但 size 字段为非零值(这种锁的合并是为了减少锁开销)。

13.4 锁的生命周期

  • 有事务日志的数据库——锁在事务期间都是有效的。在 COMMIT WORK 或者 ROLLBACK WORK 语句后被释放。

  • 没有事务日志的数据库——锁在语句执行完成时就会被释放。

13.5 动态锁管理

  • 可以指定初始大小
  • 大小可以增大到 16 倍
  • 最小增加:
    — 100,000
    — 表的大小

  锁在动态服务器中被动态分配。您可以锁定智能大对象(smart large object)的一部分,而不是整个对象。LOCKS 配置参数的值用于在共享内存中设定初始锁表(intial lock table)。如果未设置 LOCKS,将使用缺省值 2000。初始锁表被分配在共享内存的常驻部分。当锁表已满时,新的锁将被自动分配直至扩大到初始锁表大小的 16 倍。每扩大一次锁表,将最少分配 100,000 个锁或当前被锁的表的大小。所有额外的锁都将被分配到共享内存的虚拟内存部分。

  为了确保锁表不会因为单个事务的锁请求而溢出,如果事务的使用的锁超过当前分配的锁表的10%,事务持有的大对象锁将自动被升级为大对象分区锁。这种情况下,整个智能大型对象将被自动锁定。

13.6 用于smart BLOB的字节范围锁

  • 锁定Smart BLOB(binary large object)内的一组字节
  • 如果该范围内的任何一部分无法获取到就会出现锁错误
  • 自动升级为整个大对象的锁
  • 当创建 sbspace 时,使用onspaces 设置缺省锁模式
onspaces -c -S sbspace1 -p /dev/raw1 20000 -o 500 -s -Df "LOCK_MODE=BLOB"

onspaces -c -S sbspace2 -p /dev/raw2 20000 -o 500 -s -Df "LOCK_MODE=RANGE"

  字节范围(byte-range)锁功能提供一个锁设备,它与UNIX文件系统支持的锁设备类似。字节范围锁允许事务只锁定其访问的字节。更细粒度的锁定允许在同一大对象的不同字节范围内同时进行多次读取和写入。

  当现有锁与请求锁的范围发生重叠时,会导致锁等待或错误发生。只有当没有其他事务持有任何子范围内的冲突锁时,一个锁才可以被授权。如果一个锁在同一范围内被同一事务请求多次,不会导致错误发生或新锁生成。

  只有当锁表的未使用率低于 50% 时,字节锁才可以被授权。当锁表的使用率介于 50% 至 70% 时,那么首先会尝试对大对象进行锁定。如果大对象无法被锁定,则不会尝试字节范围锁。如果锁表的使用率超过 70%,将不允许使用字节范围锁,并将锁自动升级为大对象锁。锁的升级仅取决于当前锁表大小的百分比,且无法被配置。

  SinoDB动态服务器早期版本只能对整个大对象进行锁定,通过锁定大对象的分区条目来实现。现在,动态服务器允许只选择大对象的一部分进行锁定。这就是范围锁定 (range locking) 。用于大对象的范围锁由与一个特定大对象相关的范围的有序表来实现。每个范围锁和现有的锁类似,因为范围锁除了存储范围外,还存储了 rowid 和 partnum。当大对象的某一范围被锁定时,会产生一个锁,但该锁不会像其他锁一样被直接存储在锁表中。一个意向锁被放置在哈希表中,代表大型对象头(header)。这并不是大对象上的一个真正的锁,只是代表它的范围锁的一个条目。每个大对象的范围锁都与头锁(header lock)相关联,且按照字节编号排序。

  如果一个拥有缺省的字节范围锁的智能大对象被更新,相应的字节将自动被锁定。

  智能大对象使用的锁类型既可以在 sbspace 级进行配置,也可以在大对象级进行配置。指定给 sbspace 的锁模式将做为缺省设置,当在该 sbspace 中创建智能大对象时,可以覆盖此缺省设置。

  使用 onspaces 的 -Df 选项可以在创建 sbspace 时指定锁模式(LOCK_MODE选项)。 LOCK_MODE 值设置为BLOB时,意味着整个 BLOB 被锁定,设置为RANG时E指定只有访问的字节被锁定。

13.6.1 监控字节范围( Byte-Range )锁

  onstat -k 命令也可以展示所有现存的字节范围锁。如果不存在任何字节范围锁,报表内容不会发生更改。如果使用了任何字节范围锁,onstat -k 命令首先展示常规锁,然后展示字节范围锁。对于任何一个拥有字节范围锁的智能大对象来说,rowid 和头锁的分区编号都会被打印。接下来是一个列表,包含该智能大对象中现有的字节范围锁及其对应范围。此外,onstat -K 命令展示了等待获取智能 blob 上的字节范围锁的事务以及等待的范围。

  上面的 onstat -k 报表展示了一个大对象和一行中的锁。在字节范围锁部分,可以有两种状态值:

  • HDR——代表该行有字节范围锁。
  • HOLD——代表智能大对象上的所有范围锁。

强烈推荐该文章!纯技术干货。