Tôi đang làm việc trên Hệ thống có nhiều yêu cầu Cập nhật, Chèn và Xóa. Đó là lý do tại sao tôi chọn INNODB là nguyên nhân của Công cụ lưu trữ của tôi trong Khóa hàng. Chúng tôi đang cập nhật 60.000 Bản ghi mỗi 10 phút. Và chúng tôi đang sử dụng Gearman để parallise Công việc của chúng tôi trên các máy chủ khác nhau. Mã bằng PHP và chúng tôi đang sử dụng Zend Framework.Tôi làm gì sai với Khóa INNODB?
Vì vậy, hãy bắt đầu với mô tả sự cố của chúng tôi. Chúng tôi đang ghi lại các lỗi và gần như mỗi 5 - 20 phút một lỗi xảy ra.
SQLSTATE[HY000]: General error: 1205 Lock wait timeout exceeded; try restarting transaction
đơn giản mở rộng "khóa thời gian chờ đợi" isnt hữu ích cho chúng ta, bởi vì chúng tôi cố gắng cập nhật càng nhanh càng tốt.
Để biết thêm thông tin tôi đã thực hiện SHOW INNODB STATUS\G
. Một điều khiến tôi hỏi - những gì mà hack?
---TRANSACTION 0 18126657, ACTIVE 54 sec, process no 16154,
OS thread id 47956454176512 fetching rows, thread declared inside InnoDB 68 mysql tables in use 1,
locked 1 1204 lock struct(s), heap size 112624, 65338 row lock(s), undo log entries 44
MySQL thread id 3331522, query id 103362521 [ServerIP] [USER] Updating
UPDATE userproducts SET lowest_price=16.96, last_lowest_price_update='2012-09-09 20:07:30' WHERE product_id LIKE 'XXX'
65388 Hàng bị khóa, vì Bản cập nhật đơn giản này? Hay tôi chỉ bỏ lỡ điều gì đó? Theo mã PHP đã thực hiện cập nhật này.
$this->db->beginTransaction();
try {
for($i = 0; $i < count($products); $i++)
{
if(isset($products[$i]['price_total_end']))
{
if(count($products[$i]['price_total_end']) > 1)
{
$this->db->query("UPDATE userproducts SET lowest_price=".$products[$i]['price_total_end'][1].", last_lowest_price_update='".date("Y-m-d H:i:s", time())."' WHERE product_id LIKE '".$products[$i]['p_id']."'");
} elseif(count($asin[$i]['price_total_end']) == 1) {
$this->db->query("UPDATE userproducts SET lowest_price=-1, last_lowest_price_update='".date("Y-m-d H:i:s", time())."' WHERE product_id LIKE '".$products[$i]['p_id']."'");
}
}
}
$this->db->commit();
} catch (Exception $e) {
$this->db->rollBack();
echo $e->getMessage();
}
Sản phẩm Array $ có trong mục 50 cấp đầu tiên của anh ấy. Vì vậy, số lượng đếm cho đến khi 50 mà không nên là nhiều, hoặc là điều này không hoàn toàn vô lý? Điều tiếp theo mà không nên quên là, rằng wie có 20 công nhân có thể thực hiện truy vấn này đồng thời.
Thông tin quan trọng cuối cùng - tôi nghĩ - là mysql_report
.
MySQL 5.1.63-0+squeeze1 uptime 13 9:11:39 Sun Sep 9 20:44:50 2012
__ Key ___
Buffer used 55.00k of 16.00M %Used: 0.34
Current 2.92M %Usage: 18.28
Write hit 99.95%
Read hit 100.00%
__ Questions ___
Total 103.61M 89.6/s
DMS 90.73M 78.5/s %Total: 87.57
Com_ 8.57M 7.4/s 8.27
COM_QUIT 3.34M 2.9/s 3.22
QC Hits 922.81k 0.8/s 0.89
+Unknown 46.70k 0.0/s 0.05
Slow 2 s 9.33M 8.1/s 9.00 %DMS: 10.28 Log: ON
DMS 90.73M 78.5/s 87.57
INSERT 60.63M 52.4/s 58.51 66.82
UPDATE 17.80M 15.4/s 17.17 19.61
DELETE 9.55M 8.3/s 9.22 10.53
SELECT 2.76M 2.4/s 2.66 3.04
REPLACE 0 0/s 0.00 0.00
Com_ 8.57M 7.4/s 8.27
set_option 3.40M 2.9/s 3.28
show_fields 2.88M 2.5/s 2.78
begin 1.13M 1.0/s 1.09
__ SELECT and Sort ____
Scan 3.60M 3.1/s %SELECT: 130.54
Range 47 0.0/s 0.00
Full join 24 0.0/s 0.00
Range check 0 0/s 0.00
Full rng join 1 0.0/s 0.00
Sort scan 24.32k 0.0/s
Sort range 1.69M 1.5/s
Sort mrg pass 0 0/s
__ Query Cache ___
Memory usage 1.05M of 16.00M %Used: 6.57
Block Fragmnt 4.55%
Hits 922.81k 0.8/s
Inserts 2.11M 1.8/s
Insrt:Prune 2.36k:1 1.8/s
Hit:Insert 0.44:1
__ Table Locks ____
Waited 658 0.0/s %Total: 0.00
Immediate 90.73M 78.5/s
__ Tables ___
Open 128 of 128 %Cache: 100.00
Opened 3.95k 0.0/s
__ Connections __
Max used 301 of 300 %Max: 100.33
Total 3.34M 2.9/s
__ Created Temp ___
Disk table 2.88M 2.5/s
Table 2.89M 2.5/s Size: 32.0M
File 5 0.0/s
__ Threads ___
Running 21 of 168
Cached 6 of 8 %Hit: 97.09
Created 97.29k 0.1/s
Slow 0 0/s
__ Aborted ___
Clients 2.45k 0.0/s
Connects 2.75k 0.0/s
__ Bytes ___
Sent 11.04G 9.5k/s
Received 23.13G 20.0k/s
__ InnoDB Buffer Pool _____
Usage 82.86M of 1.46G %Used: 5.52
Read hit 100.00%
Pages
Free 90.70k %Total: 94.48
Data 4.92k 5.12 %Drty: 4.07
Misc 386 0.40
Latched 0 0.00
Reads 610.88G 528.3k/s
From file 816 0.0/s 0.00
Ahead Rnd 3 0.0/s
Ahead Sql 27 0.0/s
Writes 614.37M 531.3/s
Flushes 10.07M 8.7/s
Wait Free 0 0/s
__ InnoDB Lock ___
Waits 837060 0.7/s
Current 19
Time acquiring
Total 157140176 ms
Average 18772 ms
Max 59096 ms
__ InnoDB Data, Pages, Rows __
Data
Reads 919 0.0/s
Writes 11.96M 10.3/s
fsync 6.26M 5.4/s
Pending
Reads 0
Writes 0
fsync 0
Pages
Created 39.41k 0.0/s
Read 2.64k 0.0/s
Written 10.07M 8.7/s
Rows
Deleted 40.82M 35.3/s
Inserted 42.90M 37.1/s
Read 540.45G 467.4k/s
Updated 47.48M 41.1/s
Vì vậy, để quay trở lại trên khắp Câu hỏi. Tại sao chúng ta luôn nhận được lỗi chờ thời gian chờ khóa 1205?
CẬP NHẬT: Tôi đã thử một vài thứ khác. Đầu tiên, tôi đã thay đổi INSERT ... ON DUPLICATE KEY UPDATE
thành CẬP NHẬT và nếu không có gì xảy ra thì chương trình sẽ thực hiện thao tác chèn. Vì hai lý do sau đây. 1. 99,9% hoạt động này là CẬP NHẬT. 2. Tôi thougt - không rõ ràng về giả mạo đó - có lẽ một INSERT
xảy ra một khóa bảng.
Nhưng không có gì thay đổi. Sau đó tôi đã thử đoạn mã bằng khóa duy nhất. Không có gì thay đổi.
Sau đó, tôi đã có ý tưởng rằng có nhiều quy trình "ngủ" tại MySQL. Tôi điều này có được gây ra bởi rất dài chạy Gearman Scripts ?? Vì vậy, tôi đã thay đổi ví dụ Mã cho CẬP NHẬT như tôi đã đăng trước đây.
$this->db->beginTransaction();
try {
for($i = 0; $i < count($asin); $i++)
{
if(isset($asin[$i]['price_total_end']))
{
if(count($asin[$i]['price_total_end']) > 1)
{
// Es konnten Konkurrenten ausgemacht werden
if($asin[$i]['price_total_end'][0] > 0)
{
// Prüfe ob der eigene Preis der günstigste ist
if($asin[$i]['merchant_end'][0] == $merchantId)
{
// Ja der eigene Preis ist der günstigste, deshalb soll der nächste Preis der lowest sein.
$this->db->query("UPDATE userproducts SET lowest_price=".$asin[$i]['price_total_end'][1].", last_lowest_price_update='".date("Y-m-d H:i:s", time())."' WHERE product_id LIKE '".$asin[$i]['asin']."'");
} else {
$this->db->query("UPDATE userproducts SET lowest_price=".$asin[$i]['price_total_end'][0].", last_lowest_price_update='".date("Y-m-d H:i:s", time())."' WHERE product_id LIKE '".$asin[$i]['asin']."'");
}
}
} elseif(count($asin[$i]['price_total_end']) == 1) {
if($asin[$i]['price_total_end'][0] >= 0)
{
$this->db->query("UPDATE userproducts SET lowest_price=-1, last_lowest_price_update='".date("Y-m-d H:i:s", time())."' WHERE product_id LIKE '".$asin[$i]['asin']."'");
}
}
}
}
$this->db->commit();
} catch (Exception $e) {
$this->db->rollBack();
echo $e->getMessage();
}
**$this->db->closeConnection();**
Nhưng không có gì thay đổi. Các kết nối vẫn ở 301 và Chủ đề tại 32. Tôi đã làm gì sai với Mã đó chưa.
Tôi thực sự không thể đối mặt với vấn đề.
Chúng tôi rất hoan nghênh ý tưởng và số lượng của bạn. Cảm ơn các bạn.
Tôi không biết bất kỳ php nào nhưng tại sao tôi không thấy bất kỳ mysql_real_escape_string() nào? –
Thường thì chúng tôi sử dụng PDO, - sửa lỗi cho tôi nếu sai - không cần thoát. Nhưng Zend beginnTransaction() chỉ có thể xử lý truy vấn db-> không phải là chèn mà tự xử lý thoát. Tôi chỉ chuyển nó cho phương thức query(). Đó là lý do tại sao tôi đã không trốn thoát. Nhưng thông tin chúng tôi thu thập được đến từ "lưu" tệp. Nhưng tất nhiên quyền của bạn. Chúng tôi thực sự nên làm điều này. –