Hiển thị các giao dịch đang mở trong MySQL


95

Tôi đã thực hiện một số truy vấn mà không có cam kết. Sau đó, ứng dụng đã bị dừng.

Làm cách nào để hiển thị các giao dịch đang mở này và cam kết hoặc hủy bỏ chúng?


Tôi nghĩ rằng tất cả các giao dịch của bạn sẽ bị hủy khi ngắt kết nối, nhưng không chắc chắn 100%.
Johan

Bạn đang sử dụng loại bảng nào? MyISAM, InnoDB, v.v.?
cdeszaq

@cdeszaq, rõ ràng không phải MyISAM nó không có giao dịch, ngoài ra câu hỏi thực sự không liên quan gì đến bảng.
Johan

2
@Johan - Tôi chỉ đưa MyISAM làm ví dụ về loại bảng. Và nó rất quan trọng, bởi vì không phải tất cả các bảng hỗ trợ giao dịch đều hoạt động giống nhau đối với các giao dịch mất kết nối.
cdeszaq

@cdeszaq, Tài liệu MySQL nêu một điều gì đó rất khác.
Johan

Câu trả lời:


60

Làm cách nào để hiển thị các giao dịch đang mở này và cam kết hoặc hủy bỏ chúng?

Không có giao dịch mở nào, MySQL sẽ khôi phục giao dịch khi ngắt kết nối.
Bạn không thể thực hiện giao dịch (IFAIK).

Bạn hiển thị các chuỗi bằng cách sử dụng

SHOW FULL PROCESSLIST  

Xem: http://dev.mysql.com/doc/refman/5.1/en/thread-information.html

Nó sẽ không giúp ích cho bạn, bởi vì bạn không thể thực hiện một giao dịch từ một kết nối bị hỏng.

Điều gì xảy ra khi ngắt kết nối
Từ tài liệu MySQL: http://dev.mysql.com/doc/refman/5.0/en/mysql-tips.html

4.5.1.6.3. Tắt tự động kết nối lại mysql

Nếu máy khách mysql mất kết nối với máy chủ trong khi gửi câu lệnh, nó sẽ ngay lập tức và tự động cố gắng kết nối lại một lần với máy chủ và gửi lại câu lệnh. Tuy nhiên , ngay cả khi mysql kết nối lại thành công, kết nối đầu tiên của bạn đã kết thúc và tất cả các đối tượng và cài đặt phiên trước đó của bạn bị mất : bảng tạm thời, chế độ tự động gửi và các biến phiên và do người dùng xác định. Ngoài ra, bất kỳ giao dịch hiện tại nào cũng sẽ quay trở lại .

Hành vi này có thể nguy hiểm cho bạn, chẳng hạn như trong ví dụ sau khi máy chủ bị tắt và khởi động lại giữa câu lệnh thứ nhất và thứ hai mà bạn không biết:

Xem thêm: http://dev.mysql.com/doc/refman/5.0/en/auto-reconnect.html

Cách chẩn đoán và khắc phục sự cố này
Để kiểm tra tự động kết nối lại:

Nếu kết nối lại tự động xảy ra (ví dụ: do kết quả của việc gọi mysql_ping ()), thì không có dấu hiệu rõ ràng về điều đó. Để kiểm tra kết nối lại, hãy gọi mysql_thread_id()để lấy mã nhận dạng kết nối ban đầu trước khi gọi mysql_ping(), sau đó gọi mysql_thread_id()lại để xem mã nhận dạng có thay đổi hay không.

Đảm bảo rằng bạn giữ truy vấn cuối cùng của mình (giao dịch) trong ứng dụng khách để bạn có thể gửi lại nếu cần.
Và tắt chế độ tự động kết nối lại, vì điều đó rất nguy hiểm, thay vào đó hãy triển khai kết nối lại của riêng bạn để bạn biết khi nào xảy ra sụt giảm và bạn có thể gửi lại truy vấn đó.


Điều này không liên quan gì đến câu hỏi. Điều này chỉ ảnh hưởng đến máy khách mysql và OP đang nói về một ứng dụng chung, có thể có nghĩa là ứng dụng của anh ta . Ngoài ra, vì ứng dụng gọi điện đã dừng, làm thế nào nó có thể giữ giao dịch trong bộ nhớ?
cdeszaq

@cdeszaq, nó có mọi thứ liên quan đến câu hỏi. Một ứng dụng thường sử dụng máy kháchmysqld.dll AKA Và bạn giữ câu lệnh SQL có chứa toàn bộ giao dịch trong bộ nhớ để bạn có thể phát lại khi kết nối bị ngắt. Hoặc bạn giữ nó cục bộ trên đĩa, để khi khởi động lại, bạn có thể gửi lại.
Johan

Chỉ có lệnh danh sách quy trình của tôi được hiển thị trong DANH SÁCH QUY TRÌNH ĐẦY ĐỦ. Vì vậy, tôi đoán không có giao dịch mở nào cả. Phần buồn cười là autoincrement_ids dường như bị mất.
Alex,

@alex tài liệu chính thức nêu rõ điều đó, vì vậy đó là hành vi được ghi lại. Xem các liên kết.
Johan

Xinh đẹp, Johan. Đã trả lời câu hỏi và chỉ ra một số hậu quả và giải pháp cho những hậu quả đó, tất cả trong một vài đoạn văn.
Gerard ONeill

52

Mặc dù sẽ không có bất kỳ giao dịch nào còn lại trong trường hợp, như @Johan đã nói, bạn có thể xem danh sách giao dịch hiện tại trong InnoDB với truy vấn bên dưới nếu muốn.

SELECT * FROM information_schema.innodb_trx\G

Từ tài liệu :

Bảng INNODB_TRX chứa thông tin về mọi giao dịch (không bao gồm giao dịch chỉ đọc) hiện đang thực thi bên trong InnoDB, bao gồm cả giao dịch có đang chờ khóa hay không, giao dịch bắt đầu khi nào và câu lệnh SQL mà giao dịch đang thực hiện, nếu có.


Đừng cho rằng có bất kỳ cách nào để biết các giao dịch trong bảng đó có thuộc về yêu cầu / phiên cụ thể của bạn hay không?
Captain Hypertext

1
Xin lưu ý rằng công cụ \Gsửa đổi ở cuối chỉ hữu ích nếu bạn muốn định dạng đầu ra truy vấn trong công cụ mysql CLI. Nếu bạn sử dụng công cụ GUI như Mysql Workbench, bạn không cần nó.
barell

29

Bạn có thể sử dụng show innodb status(hoặc show engine innodb statusđối với các phiên bản mới hơn của mysql) để nhận danh sách tất cả các hành động hiện đang chờ xử lý bên trong công cụ InnoDB. Bị chôn vùi trong bức tường đầu ra sẽ là các giao dịch và ID quy trình nội bộ mà chúng đang chạy.

Bạn sẽ không thể buộc thực hiện cam kết hoặc khôi phục các giao dịch đó, nhưng bạn CÓ THỂ giết quá trình MySQL đang chạy chúng, về cơ bản quá trình này sẽ dẫn đến việc khôi phục. Nó giết chết kết nối của các tiến trình và khiến MySQL dọn dẹp mớ hỗn độn còn lại của nó.

Đây là những gì bạn muốn tìm kiếm:

------------
TRANSACTIONS
------------
Trx id counter 0 140151
Purge done for trx's n:o < 0 134992 undo n:o < 0 0
History list length 10
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, process no 17004, OS thread id 140621902116624
MySQL thread id 10594, query id 10269885 localhost marc
show innodb status

Trong trường hợp này, chỉ có một kết nối với công cụ InnoDB ngay bây giờ (thông tin đăng nhập của tôi, đang chạy showtruy vấn). Nếu dòng đó là một kết nối thực tế / giao dịch bị kẹt mà bạn muốn chấm dứt, thì bạn thực hiện một kill 10594.


Thực sự không cần phải kích hoạt kết nối sau khi hết thời gian chờ kết nối sẽ bị ngắt và giao dịch đang chờ xử lý từ kết nối bị hỏng không thể được cam kết để chúng có thể được gửi lại mà không sợ trùng lặp.
Johan

3
Tốt hơn là bạn nên giết các giao dịch bị mắc kẹt mà không cần đợi thời gian chờ để dọn dẹp - nếu không thì bạn có nguy cơ bị bế tắc.
Marc B

À vâng, +1 cho nhận xét đó. Quên về những bế tắc trong một phút.
Johan

@MarcB, Tại sao họ đổi nó thành show engine innodb status?
Pacerier

1

Bằng cách sử dụng truy vấn này, bạn có thể xem tất cả các giao dịch đang mở.

Liệt kê tất cả:

SHOW FULL PROCESSLIST  

nếu bạn muốn loại bỏ một id giao dịch, hãy sao chép giao dịch và hủy giao dịch bằng cách sử dụng lệnh này:

KILL <id>    // e.g KILL 16543
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.