ORA-00054: tài nguyên bận rộn và có được với NOWAIT được chỉ định hoặc hết thời gian


193

Tại sao tôi nhận được lỗi cơ sở dữ liệu này khi tôi cập nhật bảng?

LRI ở dòng 1: ORA-00054: tài nguyên bận rộn và có được với NOWAIT được chỉ định hoặc hết thời gian


22
Nó thường hữu ích nếu bạn đăng tuyên bố dẫn đến lỗi
Gary Myers

Câu trả lời:


222

Bảng của bạn đã bị khóa bởi một số truy vấn. Ví dụ: bạn có thể đã thực hiện "chọn để cập nhật" và chưa cam kết / khôi phục và thực hiện một truy vấn chọn khác. Thực hiện một cam kết / rollback trước khi thực hiện truy vấn của bạn.


47
Tôi sẽ thêm 'trong một phiên khác' vào đó. Một tình huống phổ biến là bạn đã kiểm tra bản cập nhật trong một công cụ, giả sử SQL Developer hoặc Toad, và sau đó đã cố chạy nó ở một nơi khác trong khi phiên đầu tiên vẫn giữ khóa. Vì vậy, bạn cần phải cam kết / khôi phục phiên khác trước khi bạn có thể chạy lại bản cập nhật.
Alex Poole

1
Rất có thể là DML (chèn / xóa / cập nhật) thay vì truy vấn. Và trong một phiên khác. Chỉ vì anh chàng hỏi dường như là một người mới, câu trả lời có thể đúng. Nhưng bạn KHÔNG THỂ cam kết thay mặt cho những người dùng khác trong một hệ thống sản xuất.
Arturo Hernandez

4
Chà, điều khiến tôi gặp vấn đề đó là ở Toad: Một đồng nghiệp ở cùng bàn với tôi khi tôi muốn xóa một hàng, và vì vậy tôi không thể xóa nó. Khi anh ấy chuyển sang một bảng khác, tôi đã có thể xóa các hàng. Nó có thể giúp ai đó ngoài kia. Nhưng điều này chỉ khi bạn làm việc với Con cóc bên trong các bảng chứ không phải cho các truy vấn.
DatRid

gần đây đã xảy ra trên máy chủ dàn của chúng tôi (ứng dụng Spring trên WebSphere). Giải pháp là tách tập lệnh cập nhật cơ sở dữ liệu "nguyên khối" thành các phần nhỏ hơn bằng cách di chuyển các câu lệnh gây lỗi vào một dịch vụ cập nhật riêng sử dụng một giao dịch riêng: @Transactional (tuyên truyền = Tuyên
truyền.REQUIRES_NEW

102

từ đây ORA-00054: tài nguyên bận rộn và có được với NOWAIT được chỉ định

Bạn cũng có thể tra cứu thông tin sql, tên người dùng, máy, cổng và đến quy trình thực tế giữ kết nối

SELECT O.OBJECT_NAME, S.SID, S.SERIAL#, P.SPID, S.PROGRAM,S.USERNAME,
S.MACHINE,S.PORT , S.LOGON_TIME,SQ.SQL_FULLTEXT 
FROM V$LOCKED_OBJECT L, DBA_OBJECTS O, V$SESSION S, 
V$PROCESS P, V$SQL SQ 
WHERE L.OBJECT_ID = O.OBJECT_ID 
AND L.SESSION_ID = S.SID AND S.PADDR = P.ADDR 
AND S.SQL_ADDRESS = SQ.ADDRESS;

5
Tôi đã phải xóa s.port khỏi truy vấn nhưng nó cho tôi tìm ra thủ phạm
Sibster

ổ khóa là thoáng qua. Vì vậy, nếu chèn đến, sau đó bạn cam kết ngay lập tức. nó sẽ không xuất hiện trong truy vấn này. bạn vẫn có thể gặp lỗi nếu bạn phát hành 'DDL'. trong khi giao dịch được mở xem bài viết của tôi dưới đây. Điều này thực sự dễ dàng để làm việc xung quanh.
Bob

4
Tôi đang gặp vấn đề tương tự như OP, nhưng tôi không thể thấy bất kỳ bảng nào bạn đề cập (ví dụ: chọn từ V $ LOCKED_OB DỰ ÁN, trả về ORA-00942: bảng hoặc dạng xem không tồn tại). Có ý kiến ​​gì không?
Random_forest_fanatic

3
Bạn có thể không có đủ đặc quyền để xem xét các quan điểm quản lý.
njplumridge

Theo dõi S.Portvấn đề: các tài liệu 11.2 được đề cập Portnhư một trường trong V$Session, nhưng đối với tôi, sử dụng 11.1, S.Portlà không hợp lệ. Có phải nó đã được thêm vào ngày 11.2 không?

63

Hãy giết phiên Oracle

Sử dụng truy vấn bên dưới để kiểm tra thông tin phiên hoạt động

SELECT
    O.OBJECT_NAME,
    S.SID,
    S.SERIAL#,
    P.SPID,
    S.PROGRAM,
    SQ.SQL_FULLTEXT,
    S.LOGON_TIME
FROM
    V$LOCKED_OBJECT L,
    DBA_OBJECTS O,
    V$SESSION S,
    V$PROCESS P,
    V$SQL SQ
WHERE
    L.OBJECT_ID = O.OBJECT_ID
    AND L.SESSION_ID = S.SID
    AND S.PADDR = P.ADDR
    AND S.SQL_ADDRESS = SQ.ADDRESS;

giết như

alter system kill session 'SID,SERIAL#';

(Ví dụ : alter system kill session '13,36543';)

Tham khảo http://abeytom.blogspot.com/2012/08/finding-and-fixing-ora-00054-resource.html


5
Nên báo trước câu trả lời này với những đặc quyền được yêu cầu. Tôi có CONNECTRESOURCE, nhưng không phải bất cứ thứ gì cần, với tài khoản tôi có, và nói ORA-00942: table or view does not exist. Không phải ai đọc chủ đề này cũng sẽ có SYStài khoản.
vapcguy

Nếu bạn thêm cột chọn 'S.OSUSER', bạn sẽ biết người dùng nào đang chạy giao dịch đó và sẽ rất hữu ích trong trường hợp bạn muốn kiểm tra với người dùng trước khi hủy phiên.
Narasimha

Nếu phiên được treo, thì alter system kill session '13,36543'sẽ hết thời gian và phiên sẽ không chết. Trong trường hợp đó, xem: stackoverflow.com/a/24306610/587365
Andrew Spencer

Trong khi chèn dữ liệu vào một bảng sử dụng một connection objecttrong pythontôi đã nhận một số lỗi. Sau đó python scriptđược đóng mà không đóng đúng connection object. Bây giờ tôi đang gặp lỗi "LOCKWAIT" khi tôi cố gắng thả bảng trong một phiên khác. Khi tôi cố gắng kill sessiontôi không có đủ quyền riêng tư. Những gì khác có thể được thực hiện để thoát khỏi điều này?
sjd

17

Có một công việc rất dễ dàng xung quanh vấn đề này.

Nếu bạn chạy theo dõi 10046 trên phiên của bạn (google này ... quá nhiều để giải thích). Bạn sẽ thấy rằng trước bất kỳ hoạt động DDL nào, Oracle thực hiện như sau:

BẢNG LOCK 'TABLE_NAME' KHÔNG ĐỢI

Vì vậy, nếu một phiên khác có giao dịch mở, bạn sẽ gặp lỗi. Vì vậy, sửa chữa là ... trống cuộn xin vui lòng. Cấp khóa riêng của bạn trước DDL và bỏ qua 'KHÔNG CÓ RÚT'.

Đặc biệt lưu ý:

nếu bạn đang thực hiện phân tách / thả phân vùng, chỉ cần khóa phân vùng. - vì vậy yo chỉ có thể khóa phân vùng phân vùng.

Vì vậy, ... Các bước sau đây khắc phục vấn đề.

  1. BẢNG LOCK 'TABLE TÊN'; - bạn sẽ 'chờ' (nhà phát triển gọi đây là treo). cho đến khi phiên giao dịch mở, cam kết. Đây là một hàng đợi. vì vậy có thể có một vài phiên trước bạn. nhưng bạn sẽ KHÔNG lỗi.
  2. Thực thi DDL. DDL của bạn sau đó sẽ chạy một khóa với KHÔNG CÓ. Tuy nhiên, phiên của bạn đã ngấm vào khóa. Vì vậy, bạn là tốt.
  3. DDL tự động cam kết. Điều này giải phóng các ổ khóa.

Các câu lệnh DML sẽ 'chờ' hoặc khi các nhà phát triển gọi nó là 'treo' trong khi bảng bị khóa.

Tôi sử dụng mã này trong mã chạy từ một công việc để thả phân vùng. Nó hoạt động tốt. Đó là trong một cơ sở dữ liệu liên tục chèn với tốc độ vài trăm lần chèn / giây. Không có lỗi.

nếu bạn đang tự hỏi. Làm điều này trong 11g. Tôi đã làm điều này trong 10g trước đây cũng như trong quá khứ.


3
ok, điều này là sai trong 11g, sử dụng set_ddl_timeout, Điều này chỉ khả dụng trong 11g. oracle thực hiện một cam kết trước khi thực hiện DDL, vì vậy nó giải phóng khóa. Trong 11g, bạn có thể chờ DDL. Tôi đang làm điều đó bây giờ. Hoạt động tốt.
Bob

3
trong 11g, bạn nên sử dụng LOCK TABLE tên_bảng trong chế độ ĐỘC QUYỀN;
Kamil Roman

1
Điều này thực sự hữu ích nếu bạn nhận được ORA-00054 từ các công việc hàng loạt, nhưng tôi nghi ngờ hầu hết mọi người hạ cánh ở đây (bao gồm cả OP và tôi) đang thực hiện một số phát triển và đã để lại một phiên mở khi thực hiện chèn trên cùng một bảng họ ' Đang cố gắng để thả và tái tạo. KILL SESSIONlà câu trả lời đúng cho những người này
Andrew Spencer

@Bob Ví dụ mã cho cả 11g và cách cũ sẽ tốt. Cú pháp để làm set_ddl_timeoutgì và nó nên là gì?
vapcguy

1
@vapcguy điều này làm việc cho tôi vào 11g: ALTER SYSTEM SET ddl_lock_timeout=20;xem tài liệu
rshdev

13

Lỗi này xảy ra khi tài nguyên đang bận. Kiểm tra xem bạn có bất kỳ ràng buộc tham chiếu nào trong truy vấn không. Hoặc thậm chí các bảng mà bạn đã đề cập trong truy vấn có thể đang bận. Họ có thể được tham gia với một số công việc khác sẽ được liệt kê chắc chắn trong các kết quả truy vấn sau:

SELECT * FROM V$SESSION WHERE STATUS = 'ACTIVE'

Tìm SID,

SELECT * FROM V$OPEN_CURSOR WHERE SID = --the id

1
Không phải ai cũng sẽ có quyền truy cập vào các quan điểm này. Tôi nhận được ORA-00942: table or view does not exist.
vapcguy

Trong những trường hợp như vậy, Quản trị viên DB có trách nhiệm cung cấp những thông tin đó.
Arunchunaivendan

Không phải lúc nào. Tôi đã phải cố gắng tìm ra mã này và giải quyết nó, và cả tôi và tài khoản dịch vụ của tôi đều không có các quyền này.
vapcguy

7

Điều này xảy ra khi một phiên không phải là phiên được sử dụng để thay đổi bảng có khả năng bị khóa do DML (cập nhật / xóa / chèn). Nếu bạn đang phát triển một hệ thống mới, có khả năng bạn hoặc ai đó trong nhóm của bạn đưa ra tuyên bố cập nhật và bạn có thể giết phiên mà không có nhiều hậu quả. Hoặc bạn có thể cam kết từ phiên đó khi bạn biết ai đã mở phiên.

Nếu bạn có quyền truy cập vào hệ thống quản trị SQL, hãy sử dụng nó để tìm phiên vi phạm. Và có lẽ giết nó.

Bạn có thể sử dụng v $ session và v $ lock và những người khác nhưng tôi khuyên bạn nên google cách tìm phiên đó và sau đó làm thế nào để giết nó.

Trong một hệ thống sản xuất, nó thực sự phụ thuộc. Đối với oracle 10g trở lên, bạn có thể thực thi

LOCK TABLE mytable in exclusive mode;
alter table mytable modify mycolumn varchar2(5);

Trong một phiên riêng biệt nhưng có sẵn những điều sau đây trong trường hợp mất quá nhiều thời gian.

alter system kill session '....

Nó phụ thuộc vào hệ thống nào bạn có, các hệ thống cũ có nhiều khả năng không cam kết mỗi lần. Đó là một vấn đề vì có thể có khóa lâu dài. Vì vậy, khóa của bạn sẽ ngăn chặn bất kỳ khóa mới và chờ đợi một khóa mà biết khi nào sẽ được phát hành. Đó là lý do tại sao bạn có tuyên bố khác đã sẵn sàng. Hoặc bạn có thể tìm kiếm các tập lệnh PLSQL ngoài đó thực hiện các thao tác tương tự.

Trong phiên bản 11g có một biến môi trường mới đặt thời gian chờ. Tôi nghĩ rằng nó có thể làm một cái gì đó tương tự như những gì tôi mô tả. Hãy nhớ rằng các vấn đề khóa không biến mất.

ALTER SYSTEM SET ddl_lock_timeout=20;
alter table mytable modify mycolumn varchar2(5);

Cuối cùng, tốt nhất là đợi cho đến khi có ít người dùng trong hệ thống thực hiện loại bảo trì này.


Và làm thế nào để bạn tìm ra phiên để giết alter system kill session '....nếu bạn không có quyền truy cập vào các quan điểm quản lý?
vapcguy

Điều đó tôi không biết.
Arturo Hernandez

7

Trong trường hợp của tôi, tôi khá chắc chắn rằng đó là một trong những phiên riêng của tôi đã bị chặn. Do đó, an toàn để làm như sau:

  • Tôi tìm thấy phiên vi phạm với:

    SELECT * FROM V$SESSION WHERE OSUSER='my_local_username';

    Phiên không hoạt động , nhưng nó vẫn giữ khóa bằng cách nào đó. Lưu ý rằng bạn có thể cần phải sử dụng một số khác điều kiện WHERE trong trường hợp của mình (ví dụ: thử USERNAMEhoặc MACHINEcác trường).

  • Giết phiên bằng cách sử dụng IDSERIAL#có được ở trên:

    alter system kill session '<id>, <serial#>';

Được chỉnh sửa bởi @thermz: Nếu không có truy vấn phiên mở nào trước đó hoạt động, hãy thử truy vấn này. Truy vấn này có thể giúp bạn tránh các lỗi cú pháp trong khi giết các phiên:

  • SELECT 'ALTER SYSTEM KILL SESSION '''||SID||','||SERIAL#||''' immediate;' FROM V$SESSION WHERE OSUSER='my_local_username_on_OS'

Nếu không có truy vấn phiên mở nào trước đó hoạt động, hãy thử truy vấn này.
nhiệt

5

Chỉ cần kiểm tra quá trình tổ chức phiên và giết nó. Nó trở lại bình thường.

Dưới đây SQL sẽ tìm thấy quá trình của bạn

SELECT s.inst_id,
   s.sid,
   s.serial#,
   p.spid,
   s.username,
   s.program FROM   gv$session s
   JOIN gv$process p ON p.addr = s.paddr AND p.inst_id = s.inst_id;

Sau đó giết nó

ALTER SYSTEM KILL SESSION 'sid,serial#'

HOẶC LÀ

Một số ví dụ tôi thấy trực tuyến dường như cần id cá thể cũng như thay đổi phiên giết hệ thống '130.620, @ 1';



4

select
   c.owner,
   c.object_name,
   c.object_type,
   b.sid,
   b.serial#,
   b.status,
   b.osuser,
   b.machine
from
   v$locked_object a,
   v$session b,
   dba_objects c
where
   b.sid = a.session_id
and
   a.object_id = c.object_id;
   
   ALTER SYSTEM KILL SESSION 'sid,serial#';


3

Tôi quản lý để gặp lỗi này khi chỉ cần tạo một bảng! Rõ ràng là không có vấn đề tranh chấp trên một bảng chưa tồn tại. Các CREATE TABLEtuyên bố chứa một CONSTRAINT fk_name FOREIGN KEYđiều khoản tham chiếu tới một bảng nổi đông dân cư. Tôi phải:

  • Xóa mệnh đề FOREIGN KEY khỏi câu lệnh CREATE TABLE
  • Tạo INDEX trên cột FK
  • Tạo FK

tôi chỉ có cùng một vấn đề. Tôi đã có thể tạo bảng sau khi tôi xóa định nghĩa fk khỏi câu lệnh ddl, nhưng tôi không thể thêm nó ngay cả sau khi tôi tạo chỉ mục trên cột.
vadipp

Tôi đã có thể giải quyết nó. Đầu tiên, tôi đã thêm một novalidatemệnh đề vào alter table add constraint. Điều này bằng cách nào đó cho phép nó chạy, nhưng nó khóa. Sau đó, tôi nhìn vào các khóa phiên để tìm hiểu xem phiên nào khóa. Và sau đó tôi đã giết phiên đó.
vadipp

3

Tôi đã có lỗi này xảy ra khi tôi có 2 tập lệnh tôi đang chạy. Tôi đã có:

  • Phiên SQL * Plus được kết nối trực tiếp bằng tài khoản người dùng lược đồ (tài khoản số 1)
  • Một phiên SQL * Plus khác được kết nối bằng tài khoản người dùng lược đồ khác (tài khoản số 2), nhưng kết nối qua một liên kết cơ sở dữ liệu làm tài khoản đầu tiên

Tôi đã chạy thả bảng, sau đó tạo bảng làm tài khoản # 1. Tôi đã chạy cập nhật bảng trên phiên của tài khoản # 2. Không cam kết thay đổi. Chạy lại tập lệnh thả / tạo bảng dưới dạng tài khoản # 1. Có lỗi trên drop table xlệnh.

Tôi đã giải quyết nó bằng cách chạy COMMIT;trong phiên SQL * Plus của tài khoản # 2.


Nếu bạn không có quyền thả bảng thì bạn sẽ làm gì? Câu trả lời sai
Shakeer Hussain

1
Shakeer, đó chỉ là một ví dụ về những gì tôi đã làm khi nó xảy ra với tôi - không phải là giải pháp cho vấn đề - đó là trong dòng cuối cùng của tôi - chạy a COMMIT;. Nếu bạn thậm chí không thể đánh rơi một bảng, bạn không có quyền thay đổi bất cứ điều gì có thể khiến bạn gặp phải vấn đề này ngay từ đầu.
vapcguy

-2

Tôi cũng phải đối mặt với vấn đề tương tự. Không có gì lập trình viên phải làm để giải quyết lỗi này. Tôi đã thông báo cho đội DBA tiên tri của mình. Họ giết phiên và làm việc như một lá bùa.


1
Ai đó vẫn phải làm một cái gì đó. Điều gì xảy ra nếu nhóm DBA không biết phải làm gì và làm thế nào để giết phiên? Câu trả lời không hay.
vapcguy

1
Nếu DBA không biết cách giết phiên thì anh ta không hoạt động
Shakeer Hussain

Thỉnh thoảng mọi người đều cần ôn lại cú pháp để tránh bị sai.
vapcguy

-5

Giải pháp được đưa ra bởi liên kết của Shashi là tốt nhất ... không cần liên hệ với dba hoặc người khác

tạo một bản sao lưu

create table xxxx_backup as select * from xxxx;

xóa tất cả các hàng

delete from xxxx;
commit;

chèn bản sao lưu của bạn.

insert into xxxx (select * from xxxx_backup);
commit;

10
xóa / cắt không thể thay thế cho nhau. thực hiện số lượng lớn các xóa có ý nghĩa hiệu suất lớn. Điều này thật sự tệ.
Bob

Tôi nghĩ rằng đây là một mô hình phổ biến.
Shawn Xue
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.