2015-09-09 13 views
17

Tôi đang sử dụng Laravel 5.1.Làm thế nào để tránh các vấn đề về khóa bảng DB khi sử dụng hàng đợi Laravel?

Hàng đợi được sử dụng để tìm nạp/đồng bộ hóa dữ liệu giữa một số hệ thống.

Tôi sử dụng trình điều khiển cơ sở dữ liệu, 3 "hàng đợi nghệ nhân: công việc --daemon" quy trình đang chạy mọi lúc.

Các công việc được gửi bởi cả người dùng hệ thống và người lên lịch (cron). Ba hàng đợi được sử dụng để ưu tiên các công việc.

Mọi thứ dường như chỉ hoạt động tốt - bảng công việc được lấp đầy với các bản ghi, hệ thống sẽ xử lý chúng và loại bỏ các bản ghi được thực hiện.

vấn đề Tuy nhiên sau một thời gian khóa đang bắt đầu can thiệp:

SQLSTATE[40001]: Serialization failure: 1213 Deadlock found when trying to get lock; try restarting transaction

'RuntimeException' with message 'Can't swap PDO instance while within transaction.'

SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction

tôi đã không cố gắng sử dụng một tài xế đợi được nêu ra. Tôi thực sự muốn ở lại với cơ sở dữ liệu mặc dù. Động cơ là InnoDB, bảng công việc có cấu trúc và chỉ mục mặc định.

Có cách nào để giải quyết vấn đề này không? Quan điểm của bạn là gì?

Có thể đáng nói đến là tôi gọi số DB::reconnect() bên trong lớp công việc của mình vì công nhân xếp hàng đang chạy dưới dạng daemon.

Công việc được gửi đi bằng cách sử dụng DispatchesJobs đặc điểm như mong đợi. Tôi không can thiệp vào thuật toán xếp hàng theo bất kỳ cách nào khác.

+0

Bất kỳ giải pháp cho việc này? –

+1

Không. Đã chuyển sang beanstalkd ngay bây giờ. Mặc dù tôi thích trình điều khiển DB tốt hơn vì tôi có thể theo dõi công việc và công việc thất bại bằng cách đơn giản nhìn vào bảng DB ... – MaGnetas

+0

Nghiên cứu cách Laravel xử lý các giao dịch của MySQL. Có vẻ như bạn đã bắt đầu một giao dịch, sau đó ngồi trong một thời gian dài. Giao dịch 'COMMIT' ngay khi thực tế. Kiểm tra việc sử dụng 'autocommit'. –

Trả lời

0

Bạn có thể chuyển sang MyISAM và điều đó sẽ xóa các lỗi giao dịch; nhưng đồng thời bạn sẽ mất rất nhiều chức năng tuyệt vời và độ tin cậy đi kèm với innoDB.

* Đây không phải là một lựa chọn nếu các bảng có phím nước ngoài và bạn đang dựa vào những thứ như xóa tầng và cập nhật mà chỉ được tìm thấy trong InnoDB

+1

Tôi đoán phím nước ngoài không phải là một vấn đề trong trường hợp này. Bảng không có bất kỳ mối quan hệ nào. Và việc di chuyển tạo bảng "công việc" không chỉ định động cơ. Đó thực sự có thể là giải pháp. Tuy nhiên không có giao dịch có thể có nghĩa là va chạm mà hầu như không thể theo dõi được ... – MaGnetas

1

Điều này có thể không phải là câu trả lời nhưng một số thông tin.

Khi sử dụng báo cáo SELECT ... FOR UPDATE, bạn có thể quan sát sự tranh chấp khóa (khóa chết vv ..).

select … for update where x <= y 

của mình rằng phạm vi quét với < = khóa cơ sở dữ liệu tất cả các hàng < = y, bao gồm bất kỳ khoảng trống vì vậy nếu bạn có hàng với y như thế này: 1, 3, 5 nó khóa ngay cả những không gian trống rỗng từ 1 đến 3 trong chỉ mục gọi là khoảng cách của nó khóa

có thể thấy vấn đề với lệnh này:

SHOW ENGINE INNODB STATUS; 

---TRANSACTION 72C, ACTIVE 755 sec 
4 lock struct(s), heap size 1248, 3 row lock(s), undo log entries 1 
MySQL thread id 3, OS thread handle 0x7f84a78ba700, query id 163 localhost msandbox 
TABLE LOCK table test.t trx id 72C lock mode IX 
RECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X 
RECORD LOCKS space id 19 page no 3 n bits 80 index GEN_CLUST_INDEX of table test.t trx id 72C lock_mode X locks rec but not gap 
RECORD LOCKS space id 19 page no 4 n bits 80 index age of table test.t trx id 72C lock_mode X locks gap before rec 

dòng cuối cùng

Nếu bạn có rất nhiều khoảng trống khóa trong các giao dịch của bạn ảnh hưởng đến đồng thời và hiệu suất mà bạn có thể vô hiệu hóa chúng theo hai cách khác nhau:

1- Change the ISOLATION level to READ COMMITTED. In this isolation level, it is normal and expected that query results can change during a transaction, so there is no need to create locks to prevent that from happening. 

2- innodb_locks_unsafe_for_binlog = 1. Disables the gap locks except for foreign-key constraint checking or duplicate-key checking. 

https://www.percona.com/blog/2012/03/27/innodbs-gap-locks/

+0

tất cả điều này có thể hữu ích, cảm ơn bạn. Nhưng tôi thực sự ghét làm phiền với lõi laravel. Tôi tin rằng điều này nên được giải quyết bằng cách nào đó "ra khỏi hộp". Mặc dù tôi có thể thực hiện một số thay đổi "thực hành tốt" đối với mã hoặc quy trình làm việc của mình để tránh sự cố. – MaGnetas

Các vấn đề liên quan