2012-02-04 33 views
10

Tôi có một tập lệnh PHP chạy truy vấn SELECT rồi xóa ngay hồ sơ. Có nhiều máy đang ping cùng một tập tin php và lấy dữ liệu từ cùng một bảng. Mỗi máy từ xa đang chạy trên một công việc cron.CHỌN rồi ngay lập tức XÓA hồ sơ mysql

Vấn đề của tôi là đôi khi nó không thể xóa đủ nhanh vì một số máy ping cùng một lúc.

Câu hỏi của tôi là, làm cách nào tôi có thể chọn bản ghi từ cơ sở dữ liệu và xóa nó trước khi máy tiếp theo lấy nó. Ngay bây giờ tôi chỉ thêm một sự chậm trễ ngắn nhưng nó không hoạt động rất tốt. Tôi đã thử sử dụng một giao dịch, nhưng tôi không nghĩ rằng nó được áp dụng ở đây.

Dưới đây là một đoạn mã ví dụ về kịch bản của tôi:

<?php 

$query = "SELECT * FROM `queue` LIMIT 1"; 
$result = mysql_query($query) or die(mysql_error()); 

while($row = mysql_fetch_array($result)){ 
    $email = $row['email']; 
    $campaign_id = $row['campaign']; 
} 

$queryx = "DELETE FROM `queue` WHERE `email` = '".$email."'"; 
$resultx = mysql_query($queryx) or die(mysql_error()); 

?> 

Thật đánh giá cao sự giúp đỡ.

+2

nó không được áp dụng như thế nào? âm thanh * chính xác * giống như giao dịch tốt. – mpen

+0

Bạn có được phép sử dụng các thủ tục được lưu trữ không? – dvicino

+0

@Mark - Các giao dịch có còn ngăn 'SELECT' hoạt động không? Tôi tự hỏi nếu điều này có thể không phải là vấn đề[email protected] john - Nếu chúng được chạy bởi 'cron', điểm chết của' mysql_error()) 'là gì? Tại sao không đăng nhập lỗi vào một tập tin hoặc một cái gì đó? –

Trả lời

-3

Đặt truy vấn xóa của bạn trong vòng lặp while, chỉ trong trường hợp bạn muốn tăng giới hạn từ lựa chọn của mình.

<?php 
$query = mysql_query("SELECT * FROM `queue` LIMIT 1") or die(mysql_error()); 

while($row = mysql_fetch_array($query)){ 
    mysql_query("DELETE FROM `queue` WHERE `email` = '" . $row['email'] . "' LIMIT 1") or die(mysql_error()); 
} 
?> 

Đoạn mã trên sẽ chỉ giống như chạy:

mysql_query("DELETE FROM `queue` LIMIT 1") or die(mysql_error()); 

Hãy cẩn thận sử dụng truy vấn xóa của bạn, nếu trường email là trống, nó sẽ xóa tất cả các hàng có một email trống. Thêm LIMIT 1 vào truy vấn xóa của bạn để tránh nhiều hàng bị xóa.

Để thêm một sự chậm trễ ngẫu nhiên, bạn có thể thêm một sleep để phía trên cùng của kịch bản,

ví dụ:

<?php 
$seconds = mt_rand(1,10); 
sleep($seconds); 
?> 
+1

Tôi không biết rằng điều này sẽ loại bỏ vấn đề chủng tộc/tranh chấp, nó chỉ "rút ngắn" số lượng hoạt động "có thể". Nó có thể hoạt động trong một số trường hợp, nhưng vẫn có thể có bất thường. Cũng lưu ý, vì có 'LIMIT 1',' while() 'là thừa. Vì vậy, tôi không biết điều này thực sự sẽ làm bất cứ điều gì hiệu quả cuối cùng ... –

+0

Nếu anh ta quyết định thay đổi SELECT thành hơn 1 kết quả, truy vấn xóa sẽ chỉ chạy trên kết quả đầu tiên. Vì vậy, cuối cùng nó là hiệu quả hơn và không có 'tài nguyên khôn ngoan' khác nhau để có DELETE bên ngoài vòng lặp. –

+0

"Nếu"? Có rất nhiều nếu có. Nếu OP đang xuất hiện hàng đợi, tôi hình dung nó chỉ có nghĩa là một. Điểm vẫn giống nhau (và được khuếch đại nếu có nhiều kết quả trả về cho kết quả xử lý sau này). –

6

tốt Tôi sẽ sử dụng ổ khóa bảng read more here

Khóa an toàn và áp dụng cho một phiên khách hàng. Khóa bàn chỉ bảo vệ chống lại các lần đọc không thích hợp hoặc viết bởi các phiên khác.

1

chạy truy vấn cập nhật sẽ thay đổi khóa trước khi bạn chọn. Thực hiện lựa chọn bằng khóa mới này, whicj chỉ được biết đến trong cùng một phiên.
Nếu bảng là innoDB bản ghi bị khóa và khi nó được phát hành, các lựa chọn khác sẽ không tìm thấy bản ghi.

+1

[CHỌN ... ĐỂ CẬP NHẬT VÀ CHỌN ... LOCK IN CHẾ ĐỘ CHIA SẺ Khóa Đọc] (http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html). –

+0

Chỉ câu hỏi tôi có với bình luận ở trên, bạn có thể 'DELETE' từ chế độ' SELECT ... FOR UPDATE' không? Hoặc trước tiên bạn phải mở khóa (và do đó trở lại nơi chúng tôi bắt đầu)? –

3

Bạn nên sử dụng subquery như sau ...

<?php 

$queryx = "DELETE FROM `queue` WHERE `email` IN (SELECT email FROM `queue` LIMIT 1)"; 
$resultx = mysql_query($queryx) or die(mysql_error()); 

?> 

* Lưu ý: Luôn luôn chỉ chọn những lĩnh vực bạn muốn ... cố gắng tránh chọn * ... điều này sẽ làm chậm hiệu suất

+0

Thú vị. Nếu điểm là xóa tất cả các hàng đã xếp hàng bằng email "ngẫu nhiên", điều này có thể hoạt động. –

+0

Ngoài ra, 'SELECT *' là lời khuyên tuyệt vời. 'SELECT email' là đủ. –

+0

Bạn không thể sử dụng LIMIT bên trong truy vấn phụ. Nếu không thì đây chính xác là những gì tôi đang cố gắng làm. – john

4

Nếu bạn đang sử dụng MariaDB 10:

DELETE FROM `queue` LIMIT 1 RETURNING * 

Documentation.

+0

Điều này thật tuyệt, nhưng chỉ hoạt động trong MariaDB 10.0.5 hoặc mới hơn –

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