2008-10-21 76 views
6

Tôi đang sử dụng mysql (5.0.32-Debian_7etch6-log) và tôi có tải hàng loạt chạy hàng đêm php (5.2.6) kịch bản (sử dụng Zend_Db (1.5.1) qua PDO) mà hiện những điều sau đây:lỗi nhập trùng lặp mysql khi không có mục nhập trùng lặp (số lượng lớn tải qua php)

  1. cắt bỏ một bộ 4 'nhập khẩu' bảng
  2. số lượng lớn chèn dữ liệu vào các bảng 4 'nhập khẩu' (sử dụng lại các id đã có trước đây trong các bảng, nhưng tôi đã cắt ngắn toàn bộ bảng, do đó không phải là một vấn đề, phải ?)
  3. nếu mọi thứ suôn sẻ, đổi tên bảng 'sống' thành 'temp', các bảng 'nhập' thành 'sống' và sau đó các bảng 'tạm thời' (cũ 'sống') để 'nhập'

Điều này hiệu quả trong nhiều tuần. Bây giờ tôi thỉnh thoảng mới nhận được này, đâu đó ở giữa toàn bộ quá trình tải số lượng lớn:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '911' for key 1

tâm với bạn rằng, đây không phải là id đầu tiên mà đã được trong bảng trước khi cắt ngắn rồi. Khi tôi chỉ bắt đầu lại kịch bản theo cách thủ công, nó hoạt động như một sự quyến rũ.

Bất kỳ ý tưởng nào? còn lại chỉ mục, một cái gì đó để làm với đổi tên có thể?

Ngoài ra, khi tôi kiểm tra bảng cho một mục nhập với id 911 sau đó, nó thậm chí không ở trong đó.

Trả lời

0

Một số tập lệnh khác có thể chèn vào cơ sở dữ liệu trong khi tập lệnh nhập của bạn đang chạy không?

0

Bạn đã thử bật nhật ký truy vấn để xem liệu bạn có thực sự đang chèn một bản sao không?

Bạn có thể tạo lại nó trong môi trường thử nghiệm của mình không? Không cho phép đăng nhập truy vấn trong sản xuất.

Có thể bảng đã bị hỏng nếu sự cố là chính hãng; điều này có thể được gây ra bởi một số điều, nhưng phần cứng tinh ranh hoặc mất điện là khả năng.

Kiểm tra nhật ký mysql để xem nó có gặp sự cố nào (hoặc bị lỗi) gần đây hoặc trong khoảng thời gian không.

Một lần nữa, tất cả những gì tôi có thể gợi ý là cố gắng tái tạo nó trong môi trường thử nghiệm của bạn. Tạo rất nhiều dữ liệu thử nghiệm và tải chúng liên tục.

1

Dường như có một số vấn đề về khóa hoặc thứ gì đó, tôi có thể tái tạo hành vi bằng cách chụp các phát biểu 'SELECT' tới các bảng bị ảnh hưởng và liên quan trong kết nối song song.

bây giờ tôi sử dụng DELETE FROM thay vì TRUNCATE và thay đổi RENAME TABLE báo cáo (nơi tôi đã làm 3 đổi tên cùng một lúc mỗi) vào một loạt các đơn ALTER TABLE xxx RENAME TO zzz báo cáo và không thể sao chép các lỗi nữa.

để điều này có thể được giải quyết. có thể một người khác có thể kiếm lời từ ngày tôi dành cho nghiên cứu và rất nhiều thử và lỗi.

0

Bạn đang sử dụng giao dịch?Bạn có thể loại bỏ rất nhiều loại vấn đề này với các giao dịch, đặc biệt nếu có thể khóa các bảng hoặc đặt chế độ cách ly giao dịch thành serializable. Tôi không thực sự quen thuộc với những người trên MySQL, nhưng tôi tin rằng các giao dịch chỉ hoạt động trên các bảng InnoDB (hoặc có thể là kiến ​​thức lỗi thời).

2

Các lỗi như thế này có thể xảy ra khi bảng MyISAM bị hỏng. Chạy lệnh sửa chữa trên bảng trong câu hỏi thường là tất cả những gì cần thiết để sửa chữa nó:

> repair table mytablename; 

Một giải pháp tốt hơn là không sử dụng MyISAM cho các bảng nơi dữ liệu được thay đổi liên tục - InnoDB là đạn nhiều hơn nữa, và như Paul chính xác chỉ ra, bạn có thể sử dụng giao dịch trên các bảng InnoDB, nhưng không phải trên MyISAM.

Nhân tiện, tôi sẽ tránh đổi tên bảng khi đang di chuyển - đó là điều khá khó khăn để thực hiện thường xuyên và có thể gây ra một số kết quả rất bất ngờ nếu bạn có người dùng khác trên hệ thống trong khi đổi tên đang xảy ra. Tại sao không chỉ làm một cái gì đó như thế này:

> truncate table temptable; 
> truncate table importtable; 

> #bulk insert new data 
> insert into importtable(col1,col2,col3) 
> values(1,2,3),(4,5,6),(7,8,9); 

> #now archive the live data 
> insert into temptable(col1,col2,col3) 
> select col1,col2,col3 from livetable; 

> #finally copy the new data to live 
> truncate table livetable; 
> insert into livetable(col1,col2,col3) 
> select col1,col2,col3 from importtable; 

Dĩ nhiên nếu bạn đang chèn một số lượng rất lớn của hàng thì rủi ro sẽ là tất cả các dữ liệu trực tiếp của bạn không có sẵn cho miễn là chèn cần để hoàn thành, nhưng tổng thể cách tiếp cận này ít phá hoại hơn đối với các chỉ mục, trình kích hoạt hoặc bất kỳ thứ gì khác có thể được liên kết với các bảng được đề cập.

0

Bạn đang tạo bản ghi mới có trường 'id' bị bỏ qua (hoặc NULL), NHƯNG trước đó bạn đã cập nhật một bản ghi khác và thay đổi 'id' thành '911'. Nói cách khác, bạn không thể tạo bản ghi khác nếu giá trị AUTO_INCREMENT của bảng được lấy.

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