2010-06-24 36 views
14

Để giải trí, tôi đang thay thế phần mở rộng mysqli trong ứng dụng của mình bằng PDO.PDO, mysql, giao dịch và khóa bàn

Sau một thời gian, tôi cần sử dụng giao dịch + khóa bảng.

Trong các trường hợp này, theo hướng dẫn mysql, cú pháp cần phải khác đôi chút. Thay vì gọi START GIAO DỊCH, bạn làm điều đó như vậy ...

SET autocommit=0; 
LOCK TABLES t1 WRITE, t2 READ, ...; 
... do something with tables t1 and t2 here ... 
COMMIT; 
UNLOCK TABLES; 

(http://dev.mysql.com/doc/refman/5.0/en/lock-tables-and-transactions.html)

Câu hỏi của tôi là, làm thế nào thực hiện điều này tương tác với PDO :: beginTransaction? Tôi có thể sử dụng PDO :: beginTransaction trong trường hợp này không? Hoặc tôi nên tự gửi sql "SET autocommit = 0; ... etc".

Cám ơn những lời khuyên,

Trả lời

4

Trong MySQL, bắt đầu một giao dịch khác với cách tắt autocommit, do cách Lock/Unlock công trình BẢNG. Trong MySQL, LOCK TABLES cam kết bất kỳ giao dịch mở nào, nhưng việc tắt tự động không thực sự bắt đầu một giao dịch. MySQL là buồn cười theo cách đó.

Trong PDO, bắt đầu một giao dịch sử dụng beginTransaction không thực sự bắt đầu giao dịch mới, nó chỉ tắt tự động. Trong hầu hết các cơ sở dữ liệu, điều này là lành mạnh, nhưng nó có thể có các tác dụng phụ với hành vi được đề cập của MySQL.

Bạn có lẽ không nên dựa vào hành vi này và cách nó tương tác với những điều kỳ quặc của MySQL. Nếu bạn đang đi để đối phó với hành vi của MySQL cho khóa bảng và DDL, bạn nên tránh nó. Nếu bạn muốn tắt tự động, hãy tắt nó đi bằng tay. Nếu bạn muốn mở một giao dịch, hãy mở một giao dịch bằng tay.

Bạn có thể tự do trộn các phương thức API PDO để làm việc với các giao dịch và các lệnh SQL khi không làm việc với các kỳ quặc của MySQL.

+0

"Bắt đầu một giao dịch khác với tắt tự động" Không có PDO nó không 't. Khi bạn gọi [PDO :: beginTransaction()] (http://php.net/manual/en/pdo.begintransaction.php), nó sẽ tự động tắt. – Olhovsky

+0

Điểm tốt, tôi đã cập nhật câu trả lời của mình cho phù hợp. Tôi háo hức chờ đợi ngày mà MySQL đạt được DDL lành mạnh và hành vi khóa bên trong các giao dịch ... Vâng, có thể không. Chuyển đổi sang Postgres một lúc trước. – Charles

+0

Bạn có thể kiểm tra chủ đề này không? https://stackoverflow.com/questions/47810114/php-pdo-mysql-and-how-does-it-really-deal-with-mysql-transactions Tôi vẫn không thể hiểu sự khác biệt giữa việc sử dụng 'PDO :: beginTransaction() 'có và không có' $ this-> pdo-> setAttribute (PDO :: ATTR_AUTOCOMMIT, 0); '. Bạn có thể giúp? Cảm ơn nhiều! – tonix

9

Khi bạn gọi PDO::beginTransaction(), tính năng này sẽ tự động tắt.

Vì vậy, bạn có thể làm:

$db->beginTransaction(); 
$db->exec('LOCK TABLES t1, t2, ...'); 
# do something with tables 
$db->commit(); 
$db->exec('UNLOCK TABLES'); 

Sau một cam kết() hoặc rollback(), cơ sở dữ liệu sẽ trở lại trong tự động cam kết chế độ.

+2

Đây không phải là kinh nghiệm của tôi (sử dụng mysql 5.6.27 với các bảng InnoDB), lệnh 'LOCK TABLES' về cơ bản cam kết giao dịch đã bắt đầu trước đó và tất cả các lệnh tiếp theo được cam kết riêng lẻ (tức là không có hành vi giao dịch) – mils

3

Tôi đã dành rất nhiều thời gian chạy quanh vấn đề này và tài liệu PHP trong lĩnh vực này là mơ hồ nhất. Một vài điều tôi đã tìm thấy, chạy PHP 7 với bảng MySQL InnoDB:

PDO :: beginTransaction không chỉ tắt tự động, đã kiểm tra câu trả lời được cung cấp bởi Olhovsky với mã lỗi, rollback không hoạt động ; không có hành vi giao dịch. Điều này có nghĩa là nó không thể đơn giản như vậy.

Bắt đầu một giao dịch có thể được khóa bảng sử dụng ... Tôi háo hức chờ đợi một ai đó để cho tôi biết tôi sai với điều này, nhưng đây là những lý do nó có thể là: This comment, trong đó cho thấy một bảng là không thể tiếp cận khi một giao dịch đã bắt đầu, mà không bị khóa. This PHP documentation page, bị trượt vào cuối:

...trong khi giao dịch đang hoạt động, bạn được đảm bảo rằng không ai khác có thể thực hiện thay đổi trong khi bạn đang ở giữa công việc của mình

Đối với tôi hành vi này khá thông minh và cũng cung cấp đủ chỗ cho PDO để đối phó với mọi cơ sở dữ liệu, đó là sau khi tất cả các mục tiêu. Nếu đây là những gì đang xảy ra mặc dù, nó chỉ ồ ạt dưới tài liệu và nên được gọi là cái gì khác để tránh nhầm lẫn với một giao dịch cơ sở dữ liệu thực sự, mà không bao hàm khóa.

Câu trả lời của Charles Tôi nghĩ rằng có lẽ là tốt nhất nếu bạn sau khi chắc chắn với khối lượng công việc yêu cầu đồng thời cao; làm điều đó bằng tay bằng cách sử dụng các truy vấn rõ ràng đến cơ sở dữ liệu, sau đó bạn có thể đi theo tài liệu của cơ sở dữ liệu.

Cập nhật Tôi đã có một máy chủ sản xuất và chạy bằng cách sử dụng các chức năng giao dịch PDO trong một thời gian bây giờ, thời gian gần đây sử dụng cơ sở dữ liệu Aurora AWS của (hoàn toàn tương thích với MySQL nhưng tạo để tự động mở rộng quy mô vv). Tôi đã chứng minh hai điểm này cho bản thân mình:

  • Giao dịch (hoàn toàn là khả năng thực hiện tất cả thay đổi cơ sở dữ liệu) làm việc bằng PDO :: beginTransaction(). Trong ngắn hạn, tôi biết nhiều kịch bản đã thất bại một nửa thông qua lựa chọn cơ sở dữ liệu của họ/cập nhật và tính toàn vẹn dữ liệu đã được duy trì.
  • Khóa bảng không xảy ra, tôi đã gặp lỗi sao chép chỉ mục để chứng minh điều này.

Vì vậy, để tiếp tục kết luận của tôi, có vẻ như hành vi của các chức năng này dường như thay đổi dựa trên cơ sở dữ liệu (và các yếu tố khác). Theo như tôi có thể nói cả từ kinh nghiệm và tài liệu, không có cách nào để biết lập trình những gì đang xảy ra ... whoop ...

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