cursor: pin S产生原理及解决方法

Oracle数据库性能调优
本文介绍了Oracle数据库中cursor:pinS等待事件的原因及其解决方法,包括如何通过查询SQL语句来定位问题,以及如何通过调整SQL执行策略来降低并发争用。

转自:http://www.dbafree.net/?p=778

今天晚上在一个比较重要的库上,CPU严重的冲了一下,导致DB响应变慢,大量应用连接timeout,紧接着LISTENER就挂了,连接数也满了等一连串问题。

我们的监控抓取了当时系统的等待事件,ACTIVE SQL及SESSION_WAIT等待事件,所以问题比较容量定位,查看下监控,马上就发现出问题的时间点上出现大量的cusor:pin S,这个等待事件很常见。

再通过查询持有的等待事件cursor: pin S的会话正在执行的SQL语句发现仅是一条简单的SQL。通常内存中latch pin操作是相当快的,如果出现等待了,应该很可能就是该SQL执行的过于频繁。latch在Oracle中是一种低级锁,用于保护内存里的数据结构,提供的是串行访问机制,而mutex是Oracle 10gR2引入的,也是为实现串行访问控制的功能,并替换部分latch。

可以通过下面的SQL进行查询:

--查询sql
SELECT a.*, s.sql_text
  FROM v$sql s,
       (SELECT sid,
               event,
               wait_class,
               p1 cursor_hash_value,
               p2raw Mutex_value,
               TO_NUMBER (SUBSTR (p2raw, 1, 8), 'xxxxxxxx') hold_mutex_x_sid
          FROM v$session_wait
         WHERE event LIKE 'cursor%') a
 WHERE s.HASH_VALUE = a.p1

--Parameter说明
P1 Hash value of cursor

P2 Mutex value
64 bit platforms
8 bytes are used.
Top 4 bytes hold the session id (if the mutex is held X)
Bottom 4 bytes hold the ref count (if the mutex is held S).

32 bit platforms
4 bytes are used.
Top 2 bytes hold the session id (if the mutex is held X)
Bottom 2 bytes hold the ref count (if the mutex is held S).

P3 Mutex where (an internal code locator) OR'd with Mutex Sleeps

在每个child cursor下面都有一个mutexes这样的简单内存结构,当有session要执行该SQL而需要pin cursor操作的时候,session只需要以shared模式set这个内存位+1,表示session获得该mutex的shared mode lock.可以有很多session同时具有这个mutex的shared mode lock;但在同一时间,只能有一个session在操作这个mutext +1或者-1。+1 -1的操作是排它性的原子操作。如果因为session并行太多,而导致某个session在等待其他session的mutext +1/-1操作,则该session要等待cursor: pin S等待事件。

当看到系统有很多session等待cursor: pin S事件的时候,要么是CPU不够快,要么是某个SQL的并行执行次数太多了而导致在child cursor上的mutex操作争用。如果是硬件的问题,则可以升级硬件。

如果是SQL执行频率太高。最简单的做法是,将一条SQL拆分成多条SQL。增加SQL的版本数来降低并发。如一个SQL:

select name from acct where acctno=:1

可以改为如下4个SQL,则并发的争用可以下降4倍。

     select /*A*/ name from acct where acctno=:1
     select /*B*/ name from acct where acctno=:1
     select /*C*/ name from acct where acctno=:1
     select /*D*/ name from acct where acctno=:1

 

另外,我们还会经常碰到另外一个等待事件“cursor: pin S wait on X”,这个等待事件主要是由硬解析引起的,解释如下:
“cursor: pin S wait on X” wait event is mostly related to mutex and hard parse.
- When a process hard parses the SQL statement, it should acquire exclusive
  library cache pin for the corresponding LCO.
- This means that the process acquires the mutex in exclusive mode.
- Another process which also executes the same query needs to acquire the mutex
  but it’s being blocked by preceding process. The wait event is “cursor: pin S wait on X”.

cursor: pin S,cursor: pin X,cursor: pin S wait on X这三个等待事件,实际上就是替代了cursor的library cache pin,pin S代表执行(share pin),pin X代表解析(exclusive pin),pin S wait on X代表执行正在等待解析操作。这里需要强调一下,它们只是替换了访问cursor的library cache pin,而对于访问procedure这种实体对象,依然是传统的library cache pin。

参考:

https://supporthtml.oracle.com/epmos/faces/ui/km/DocumentDisplay.jspx?_afrLoop=5051110464464000&id=1310764.1&_afrWindowMode=0&_adf.ctrl-state=fu77hl3v2_4

http://www.hellodb.net/2010/07/oracle-library-cache.html这篇文章不错,每次看都能有所收获。

 

### LCD2864 的使用方法及 C 语言编程示例 LCD2864 是一种常见的字符型液晶显示模块,通常用于嵌入式系统中显示文字信息。以下是关于其基本工作原理、初始化过程以及如何通过 C 语言实现控制的相关说明。 #### 工作原理概述 LCD2864 属于 HD44780 控制器驱动的液晶屏系列之一。它支持两种数据传输模式:8 位模式和 4 位模式。由于 4 位模式可以减少硬件资源占用,在实际应用中更为常见[^1]。该显示屏具有两行每行最多可显示 16 个字符的能力(尽管型号名称可能暗示不同的尺寸)。为了操作此设备,需遵循特定指令集来完成诸如清屏、设置光标位置等功能调用。 #### 初始化流程描述 在开始写入任何字符之前,必须先执行一系列命令以正确配置 LCD 显示器的状态。这些步骤包括但不限于设定接口宽度(即选择 4 或者 8 数据线),开启/关闭显示器本身及其上的游标或者闪烁标志等等[^2]。 下面给出的是基于 AVR 单片机平台的一个典型初始化函数: ```c #include <avr/io.h> #define LCD_PORT PORTB // Define port used to connect lcd data pins DB0-DB7 #define RS_PIN PB0 // Register select pin connected at PB0 #define RW_PIN PB1 // Read/write pin connected at PB1 #define EN_PIN PB2 // Enable pin connected at PB2 void delay_ms(unsigned int ms); // Function prototype declarations here... /* Initialize the LCD */ void init_LCD(void){ DDRB |= (1<<RS_PIN)|(1<<RW_PIN)|(1<<EN_PIN); _delay_ms(15); /* Wait more than 15ms after power on */ write_Nibble(0x03); /* Send function set command three times with N=1, F=0 */ pulse_Enable(); _delay_us(4100); write_Nibble(0x03); pulse_Enable(); _delay_us(100); write_Nibble(0x03); pulse_Enable(); write_Nibble(0x02); /* Set interface length as four bits mode */ pulse_Enable(); send_Command(0x28); /* Function set: DL=0,N=1,F=0 => Four-bit Interface,two-line display and 5*7 dot matrix characters*/ send_Command(0x0C); /* Display ON/OFF control: D=1,C=0,B=0 => Display On,cursor Off,blinking Off */ send_Command(0x06); /* Entry Mode Set: I/D=1,S=0 => Increment cursor position after each character written,no shift of entire display */ } ``` 上述代码片段展示了如何利用四条独立发送高四位字节的方式来进行完整的八位指令传递给 LCD 模块的过程[^3]。注意这里定义了一些辅助宏用来简化端口操作,并且假设已经实现了 `_delay_*` 函数族提供精确延时功能。 对于字符串打印到屏幕这样的常用需求,则可以通过如下方式达成: ```c /* Print string s starting from current cursor location */ void print_String(char *s){ while(*s != '\0'){ send_Char(*s++); } } // Example usage inside main program loop: print_String("Hello World!"); send_Command(0xC0); // Move Cursor To Second Line Start Position print_String("Embedded System"); ``` 以上就是针对 LCD2864 设备的一般性介绍连同简单的 C 实现例子。具体细节可能会依据所选用微控制器的不同而有所变化,请参照相应开发板手册调整连接关系与寄存器地址映射等内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值