<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Administración de ORACLE en Español &#187; kill -9</title>
	<atom:link href="http://colacios.es/blog/WordPress3/tag/kill-9/feed/" rel="self" type="application/rss+xml" />
	<link>http://colacios.es/blog/WordPress3</link>
	<description>Administración de Base de datos ORACLE en español</description>
	<lastBuildDate>Tue, 11 Mar 2014 12:56:35 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>ORA-00054: recurso ocupado y obtenido con NOWAIT especificado o timeout vencido &#124;&#124; Bloqueos</title>
		<link>http://colacios.es/blog/WordPress3/ora-00054-recurso-ocupado-y-obtenido-con-nowait-especificado-o-timeout-vencido-bloqueos/</link>
		<comments>http://colacios.es/blog/WordPress3/ora-00054-recurso-ocupado-y-obtenido-con-nowait-especificado-o-timeout-vencido-bloqueos/#comments</comments>
		<pubDate>Fri, 18 Oct 2013 15:16:08 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Administración Oracle]]></category>
		<category><![CDATA[ORA-?????]]></category>
		<category><![CDATA[bloqueos]]></category>
		<category><![CDATA[kill -9]]></category>
		<category><![CDATA[kill session]]></category>
		<category><![CDATA[ORA-00054]]></category>
		<category><![CDATA[ps -ef]]></category>

		<guid isPermaLink="false">http://colacios.es/blog/WordPress3/?p=627</guid>
		<description><![CDATA[Este error suele aparecer cuando existen bloqueos esperando a que otro usuario termine una operación, para poder realizar la suya. Uno de los más comunes que suelen suceder  es cuando se hacen &#8220;truncate&#8221; o &#8220;drop&#8221; de tablas y no nos &#8230; <a href="http://colacios.es/blog/WordPress3/ora-00054-recurso-ocupado-y-obtenido-con-nowait-especificado-o-timeout-vencido-bloqueos/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p style="text-align: justify;">Este error suele aparecer cuando existen bloqueos esperando a que otro usuario termine una operación, para poder realizar la suya. Uno de los más comunes que suelen suceder  es cuando se hacen &#8220;truncate&#8221; o &#8220;drop&#8221; de tablas y no nos deja hacerlo porque las tabla/s están bloqueada/s por otros procesos de ese mismo u otros usuarios.</p>
<p style="text-align: justify;">En el ejemplo que explico seguidamente el problema se produjo porque al llenarse un tablespace (datafile al 100%) realizando unos &#8220;inserts&#8221; en una tabla, el proceso se quedó bloqueado hasta poder hacer la inserción. En  mi caso, como podía volver a lanzar el proceso sin problema, y no quería ampliar más la ocupación del tablespace afectado. Decidí matar los procesos que estaban bloqueados y volver a lanzar la ejecución de los inserts que provocaron por error que se llenara el tablespace.</p>
<p style="text-align: justify;">En este ejemplo sólo se va a tratar el problema del bloqueo, no se va a tener en cuenta el problema de la falta de espacio del tablespace, porque eso fue debido a otra causa, pero que fue, en parte el causante del error que os voy a explicar y cuya solución veréis en esta entrada de blog.</p>
<p style="text-align: justify;">Entro en detalle:</p>
<p style="text-align: justify;">Al intentar hacer un truncate de una tabla salta el error:</p>
<p style="text-align: justify;">ORA-00054: recurso ocupado y obtenido con NOWAIT especificado o timeout vencido</p>
<pre>SQL&gt; <strong>truncate table &lt;mi_tabla&gt; ;</strong>
truncate table &lt;mitabla&gt;
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified</pre>
<p style="text-align: justify;">Esto ocurre porque se ha bloqueado uno o varios registros mediante setencias SQL. Select´s especificados como &#8220;NO WAIT&#8221; o &#8220;FOR UPDATE NOWAIT&#8221; o por una operación DDL que fue bloqueada. La solución podía pasar por hacer el commit o rollback. El commit no funcionó porque no hay espacio en el tablespace. El rollback no se probó, porque preferí matar la sesión que estaba provocando el error tal y como explico seguidamente.</p>
<p style="text-align: justify;">En Oracle hay una vista llamada v$lock que nos indica los objetos que se encuentran en bloqueo, el identificador de usuario,  sesion y el tipo de bloqueo. Una join con la tabla dba_objects nos proporcionará ademas el nombre y tipo de los objetos bloqueados. La consulta seria como sigue:</p>
<pre>SELECT
     decode(L.TYPE,'TM','TABLE','TX','Record(s)') TYPE_LOCK,
     decode(L.REQUEST,0,'NO','YES') WAIT,
     S.OSUSER OSUSER_LOCKER,
     S.PROCESS PROCESS_LOCKER,
     S.USERNAME DBUSER_LOCKER,
     O.OBJECT_NAME OBJECT_NAME,
     O.OBJECT_TYPE OBJECT_TYPE,
     CONCAT(' ',s.PROGRAM) PROGRAM,
     O.OWNER OWNER
 FROM v$lock l,dba_objects o,v$session s
 WHERE l.ID1 = o.OBJECT_ID AND s.SID =l.SID AND l.TYPE in ('TM','TX','UL');</pre>
<p style="text-align: justify;">Existen varios tipos de bloqueo (TM,TX,UL):</p>
<p style="text-align: justify;"><strong>TM</strong> – DML enqueue. Bloqueos a nivel de tabla. Los bloqueos a nivel de tabla son creados cuando se ejecuta una sentencia DML del tipo: update, insert, delete, select ..for update sobre la tabla entera.</p>
<p style="text-align: justify;">Por ejemplo:</p>
<pre style="text-align: justify;">DELETE from &lt;mi_tabla&gt;;
TRUNCATE &lt;mi_tabla&gt;;
UPDATE &lt;mi_tabla&gt; SET campo1 = valor;</pre>
<p style="text-align: justify;">haciendo un &#8220;delete&#8221; fue el error en este ejemplo. Por tanto tenía un bloqueo a nivel de tabla.</p>
<p style="text-align: justify;"><strong>TX</strong> – Transaction enqueue. Bloqueos a nivel de fila. Los bloqueos a nivel de fila se crean cuando se ejecutan senencias DML contra un conjunto de registros específicos.</p>
<p style="text-align: justify;"><strong>UL</strong> – User supplied.  Bloqueos a nivel de usuario.</p>
<p style="text-align: justify;">Para solucionar el error:</p>
<p style="text-align: justify;">Nos conectaremos como system a Oracle y ejecutaremos la siguiente consulta para ver si existe algún bloqueo:</p>
<pre style="text-align: justify;"> SQL&gt; show user
 USER is "SYSTEM"
 SQL&gt; select * from v$lock where request!=0;</pre>
<p style="text-align: justify;">Si hacemos una join con v$open_cursor podremos ver que consulta es la que se encuentra parada a la espera de que se produzca el desbloqueo para poder ejecutarse.</p>
<p style="text-align: justify;">En la consulta siguiente podemos ver las sentencias paradas esperando a que termine un bloqueo, la sentencia que quieren ejecutar y el id de proceso que las está bloqueando:</p>
<pre style="text-align: justify;">select /*+ ordered
    no_merge(L_WAITER)
    no_merge(L_LOCKER) use_hash(L_LOCKER)
    no_merge(S_WAITER) use_hash(S_WAITER)
    no_merge(S_LOCKER) use_hash(S_LOCKER)
    use_nl(O)
    use_nl(U)
    */
    /* first the table-level locks (TM) and mixed TM/TX TX/TM */
    S_LOCKER.OSUSER OS_LOCKER,
    S_LOCKER.USERNAME LOCKER_SCHEMA,
    S_LOCKER.PROCESS LOCKER_PID,
    S_WAITER.OSUSER OS_WAITER,
    S_WAITER.USERNAME WAITER_SCHEMA,
    S_WAITER.PROCESS WAITER_PID,
    'Table lock (TM): '||U.NAME||'.'||O.NAME||
    ' - Mode held: '||
    decode(L_LOCKER.LMODE,
    0, 'None', /* same as Monitor */
    1, 'Null', /* N */
    2, 'Row-S (SS)', /* L */
    3, 'Row-X (SX)', /* R */
    4, 'Share', /* S */
    5, 'S/Row-X (SSX)', /* C */
    6, 'Exclusive', /* X */
    '???: '||to_char(L_LOCKER.LMODE))||
    ' / Mode requested: '||
    decode(L_WAITER.REQUEST,
    0, 'None', /* same as Monitor */
    1, 'Null', /* N */
    2, 'Row-S (SS)', /* L */
    3, 'Row-X (SX)', /* R */
    4, 'Share', /* S */
    5, 'S/Row-X (SSX)', /* C */
    6, 'Exclusive', /* X */
    '???: '||to_char(L_WAITER.REQUEST))
    SQL_TEXT_WAITER
from
    V$LOCK L_WAITER,
    V$LOCK L_LOCKER,
    V$SESSION S_WAITER,
    V$SESSION S_LOCKER,
    sys.OBJ$ O,
    sys.USER$ U
where S_WAITER.SID = L_WAITER.SID
    and L_WAITER.TYPE IN ('TM')
    and S_LOCKER.sid = L_LOCKER.sid
    and L_LOCKER.ID1 = L_WAITER.ID1
    and L_WAITER.REQUEST &gt; 0
    and L_LOCKER.LMODE &gt; 0
    and L_WAITER.ADDR != L_LOCKER.ADDR
    and L_WAITER.ID1 = O.OBJ#
    and U.USER# = O.OWNER#
union
    select /*+ ordered
        no_merge(L_WAITER)
        no_merge(L_LOCKER) use_hash(L_LOCKER)
        no_merge(S_WAITER) use_hash(S_WAITER)
        no_merge(S_LOCKER) use_hash(S_LOCKER)
        no_merge(L1_WAITER) use_hash(L1_WAITER)
        no_merge(O) use_hash(O)
        */
        /* now the (usual) row-locks TX */
        S_LOCKER.OSUSER OS_LOCKER,
        S_LOCKER.USERNAME LOCKER_SCHEMA,
        S_LOCKER.PROCESS LOCK_PID,
        S_WAITER.OSUSER OS_WAITER,
        S_WAITER.USERNAME WAITER_SCHEMA,
        S_WAITER.PROCESS WAITER_PID,
        'TX: '||O.SQL_TEXT SQL_TEXT_WAITER
    from
        V$LOCK L_WAITER,
        V$LOCK L_LOCKER,
        V$SESSION S_WAITER,
        V$SESSION S_LOCKER,
        V$_LOCK L1_WAITER,
        V$OPEN_CURSOR O
    where S_WAITER.SID = L_WAITER.SID
        and L_WAITER.TYPE IN ('TX')
        and S_LOCKER.sid = L_LOCKER.sid
        and L_LOCKER.ID1 = L_WAITER.ID1
        and L_WAITER.REQUEST &gt; 0
        and L_LOCKER.LMODE &gt; 0
        and L_WAITER.ADDR != L_LOCKER.ADDR
        and L1_WAITER.LADDR = L_WAITER.ADDR
        and L1_WAITER.KADDR = L_WAITER.KADDR
        and L1_WAITER.SADDR = O.SADDR
        and O.HASH_VALUE = S_WAITER.SQL_HASH_VALUE
/</pre>
<p style="text-align: justify;">Pero sino devuelve nada, que era lo que me pasaba a mi, y como el error me lo generaba un delete o un truncate, tuve que ejecutar la siguiente consulta para ver que era lo que tenía que &#8220;matar&#8221;.</p>
<pre>SQL&gt; SELECT mode_held FROM dba_dml_locks where OWNER='&lt;<em>mi_usuario</em>&gt;';
MODE_HELD
-------------
Row-X (SX)
Row-X (SX)
Row-X (SX)</pre>
<p>Seguidamente podía listar los bloqueos que ocurrían en ese momento en la base de datos.Y  por medio de los campos LMODE y REQUEST saber de que tipo son :</p>
<p>none<br />
null (NULL)<br />
row-S (SS)<br />
row-X (SX)<br />
share (S)<br />
S/Row-X (SSX)<br />
exclusive (X)</p>
<pre>SELECT oracle_username || ' (' || s.osuser || ')' username
    ,  s.sid || ',' || s.serial# sess_id
    ,  owner || '.' || object_name object
    ,  object_type
    ,  decode( l.block
       ,       0, 'Not Blocking'
       ,       1, 'Blocking'
       ,       2, 'Global') status
    ,  decode(v.locked_mode
      ,       0, 'None'
      ,       1, 'Null'
      ,       2, 'Row-S (SS)'
      ,       3, 'Row-X (SX)'
      ,       4, 'Share'
      ,       5, 'S/Row-X (SSX)'
      ,       6, 'Exclusive', TO_CHAR(lmode)) mode_held
FROM v$locked_object v,dba_objects d,v$lock l,v$session s
WHERE v.object_id = d.object_id
   and v.object_id = l.id1
   and v.session_id = s.sid
ORDER BY oracle_username,session_id
/</pre>
<p>Sale algo como &#8230; <a href="http://colacios.es/blog/WordPress3/wp-content/uploads/2013/10/pant_bloqueo_usuario1.jpg"><img class="aligncenter size-full wp-image-637" title="pant_bloqueo_usuario1" src="http://colacios.es/blog/WordPress3/wp-content/uploads/2013/10/pant_bloqueo_usuario1.jpg" alt="" width="833" height="53" /></a></p>
<p style="text-align: justify;">Intento matarlo &#8230;</p>
<pre style="text-align: justify;">SQL&gt; alter system kill session '215,2774';
alter system kill session '215,2774'
*
ERROR at line 1:
ORA-00031: session marked for kill</pre>
<p style="text-align: justify;">Pruebo entonces con immediate y si me funciona.</p>
<pre style="text-align: justify;">alter system kill session '215,2774' immediate;</pre>
<p style="text-align: justify;">Pero si lo anterior fallase buscaría por medio de esta SQL el  SPID que es el número de proceso de Linux/unix que usaría para matar el proceso a nivel de S.O.</p>
<pre style="text-align: justify;">SELECT s.sid, p.spid, s.osuser, s.program
FROM   v$process p, v$session s
WHERE  p.addr = s.paddr;</pre>
<p style="text-align: justify;">La consulta anterior me muestra todos los procesos, buscaría el SID del proceso que quiero matar y me anotaría el campo SPID que es el que definitivamente usaré para matar el proceso. Pero si quiero sólo buscar el SID de la que quiero matar, ejecutaría:</p>
<pre style="text-align: justify;">SELECT s.sid, p.spid, s.osuser, s.program
FROM   v$process p, v$session s
WHERE  p.addr = s.paddr and s.sid = '<em>215</em>'; <strong>--&gt; SID basado en mi ejemplo</strong></pre>
<p style="text-align: justify;">Para saber cual es el SPID busco con el campo SID que me salia en la primera consulta. Es el primer valor antes de la &#8220;,&#8221; que uso en el&#8221; alter kill session &#8230;&#8221;</p>
<p style="text-align: justify;">Para matar el proceso a nivel de S.O en mi caso un Linux. Se hace así:</p>
<p style="text-align: justify;">Conectado como root al linux &#8230;</p>
<pre style="text-align: justify;"># ps -ef |grep  &lt;<em>SPID</em>&gt; --&gt; Donde SPID es el número de proceso
# kill -9 &lt;<em>SPID</em>&gt;</pre>
<p style="text-align: justify;">
]]></content:encoded>
			<wfw:commentRss>http://colacios.es/blog/WordPress3/ora-00054-recurso-ocupado-y-obtenido-con-nowait-especificado-o-timeout-vencido-bloqueos/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
