Hướng dẫn mysql select for update example - mysql chọn cho ví dụ cập nhật

15.7.2.4 & NBSP; Khóa đọc

Nếu bạn truy vấn dữ liệu và sau đó chèn hoặc cập nhật dữ liệu liên quan trong cùng một giao dịch, câu lệnh SELECT thông thường không bảo vệ đủ. Các giao dịch khác có thể cập nhật hoặc xóa cùng một hàng bạn vừa truy vấn. InnoDB hỗ trợ hai loại bài đọc khóa cung cấp thêm sự an toàn:

  • ________số 8

    Đặt khóa chế độ chia sẻ trên bất kỳ hàng nào được đọc. Các phiên khác có thể đọc các hàng, nhưng không thể sửa đổi chúng cho đến khi giao dịch của bạn cam kết. Nếu bất kỳ hàng nào trong số các hàng này được thay đổi bởi một giao dịch khác chưa cam kết, truy vấn của bạn sẽ đợi cho đến khi giao dịch đó kết thúc và sau đó sử dụng các giá trị mới nhất.

    Ghi chú

    SELECT ... FOR SHARE là một sự thay thế cho

    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    0, nhưng
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    1 vẫn có sẵn để tương thích ngược. Các tuyên bố là tương đương. Tuy nhiên,
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    2 hỗ trợ các tùy chọn
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    3,
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    4 và
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    5. Xem khóa Đọc đồng thời với Nowait và bỏ qua khóa.

    Trước MySQL 8.0.22, SELECT ... FOR SHARE yêu cầu đặc quyền SELECT và ít nhất một trong các đặc quyền

    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    8,
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    9 hoặc
    SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
    0. Từ MySQL 8.0.22, chỉ cần đặc quyền SELECT.

    Từ MySQL 8.0.22, các câu lệnh SELECT ... FOR SHARE không có được khóa đọc trên bảng tài trợ MySQL. Để biết thêm thông tin, xem đồng thời bảng cấp.

  • SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
    3

    Đối với chỉ mục ghi lại các cuộc gặp gỡ tìm kiếm, khóa các hàng và bất kỳ mục chỉ mục liên quan nào, giống như khi bạn đã phát hành câu lệnh

    SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
    0 cho các hàng đó. Các giao dịch khác bị chặn cập nhật các hàng đó, không thực hiện SELECT ... FOR SHARE hoặc đọc dữ liệu trong một số mức cách ly một số giao dịch. Các lần đọc nhất quán bỏ qua bất kỳ khóa được đặt trên các bản ghi tồn tại trong chế độ xem đọc. .

    SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
    6 yêu cầu đặc quyền SELECT và ít nhất một trong các đặc quyền
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    8,
    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    9 hoặc
    SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
    0.

Các mệnh đề này chủ yếu hữu ích khi xử lý dữ liệu có cấu trúc cây hoặc có cấu trúc đồ thị, trong một bảng hoặc phân chia trên nhiều bảng. Bạn đi qua các cạnh hoặc nhánh cây từ nơi này sang nơi khác, trong khi có quyền quay lại và thay đổi bất kỳ giá trị nào của con trỏ này.pointer values.

Tất cả các khóa được đặt bởi các truy vấn

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
2 và
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
2 được phát hành khi giao dịch được thực hiện hoặc quay lại.

Ghi chú

SELECT ... FOR SHARE là một sự thay thế cho

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
0, nhưng
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
1 vẫn có sẵn để tương thích ngược. Các tuyên bố là tương đương. Tuy nhiên,
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
2 hỗ trợ các tùy chọn
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
3,
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4 và
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
5. Xem khóa Đọc đồng thời với Nowait và bỏ qua khóa.

Trước MySQL 8.0.22, SELECT ... FOR SHARE yêu cầu đặc quyền SELECT và ít nhất một trong các đặc quyền

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
8,
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
9 hoặc
SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
0. Từ MySQL 8.0.22, chỉ cần đặc quyền SELECT.

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2) FOR UPDATE;

Từ MySQL 8.0.22, các câu lệnh SELECT ... FOR SHARE không có được khóa đọc trên bảng tài trợ MySQL. Để biết thêm thông tin, xem đồng thời bảng cấp.

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;

SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
3

Đối với chỉ mục ghi lại các cuộc gặp gỡ tìm kiếm, khóa các hàng và bất kỳ mục chỉ mục liên quan nào, giống như khi bạn đã phát hành câu lệnh

SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
0 cho các hàng đó. Các giao dịch khác bị chặn cập nhật các hàng đó, không thực hiện SELECT ... FOR SHARE hoặc đọc dữ liệu trong một số mức cách ly một số giao dịch. Các lần đọc nhất quán bỏ qua bất kỳ khóa được đặt trên các bản ghi tồn tại trong chế độ xem đọc. .

SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
6 yêu cầu đặc quyền SELECT và ít nhất một trong các đặc quyền
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
8,
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
9 hoặc
SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
0.

Các mệnh đề này chủ yếu hữu ích khi xử lý dữ liệu có cấu trúc cây hoặc có cấu trúc đồ thị, trong một bảng hoặc phân chia trên nhiều bảng. Bạn đi qua các cạnh hoặc nhánh cây từ nơi này sang nơi khác, trong khi có quyền quay lại và thay đổi bất kỳ giá trị nào của con trỏ này.

SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;

Tất cả các khóa được đặt bởi các truy vấn

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
2 và
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
2 được phát hành khi giao dịch được thực hiện hoặc quay lại.

Khóa đọc chỉ có thể khi AutoCommit bị vô hiệu hóa (bằng cách bắt đầu giao dịch với

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
3 hoặc bằng cách đặt
SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
4 thành 0.

Một mệnh đề đọc khóa trong một câu lệnh bên ngoài không khóa các hàng của bảng trong một trình điều khiển con lồng nhau trừ khi một điều khoản đọc khóa cũng được chỉ định trong trình điều khiển con. Ví dụ: câu lệnh sau không khóa các hàng trong bảng

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
5.

Để khóa các hàng trong bảng

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;
5, thêm một mệnh đề đọc khóa vào trình điều khiển con:

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;

Một

# Session 1:

mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

mysql> INSERT INTO t (i) VALUES(1),(2),(3);

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+

# Session 2:

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.

# Session 3:

mysql> START TRANSACTION;

mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+
4 đọc dữ liệu mới nhất có sẵn, đặt khóa độc quyền trên mỗi hàng mà nó đọc. Do đó, nó đặt cùng một khóa mà SQL
SELECT * FROM parent WHERE NAME = 'Jones' FOR SHARE;
0 đã tìm kiếm sẽ đặt trên các hàng.

Mô tả trước đó chỉ là một ví dụ về cách thức hoạt động của

# Session 1:

mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

mysql> INSERT INTO t (i) VALUES(1),(2),(3);

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+

# Session 2:

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.

# Session 3:

mysql> START TRANSACTION;

mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+
4. Trong MySQL, nhiệm vụ cụ thể là tạo một mã định danh duy nhất thực sự có thể được thực hiện chỉ bằng một quyền truy cập duy nhất vào bảng:

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

Câu lệnh SELECT chỉ đơn thuần lấy thông tin định danh (cụ thể cho kết nối hiện tại). Nó không truy cập bất kỳ bảng.

Khóa đọc đồng thời đọc với nowait và bỏ qua

Nếu một hàng bị khóa bởi một giao dịch, giao dịch

# Session 1:

mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

mysql> INSERT INTO t (i) VALUES(1),(2),(3);

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+

# Session 2:

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.

# Session 3:

mysql> START TRANSACTION;

mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+
4 hoặc SELECT ... FOR SHARE yêu cầu cùng một hàng bị khóa phải đợi cho đến khi giao dịch chặn phát hành khóa hàng. Hành vi này ngăn các giao dịch cập nhật hoặc xóa các hàng được truy vấn để cập nhật bởi các giao dịch khác. Tuy nhiên, việc chờ khóa hàng được phát hành là không cần thiết nếu bạn muốn truy vấn quay lại ngay lập tức khi hàng được yêu cầu bị khóa hoặc nếu loại trừ các hàng bị khóa khỏi bộ kết quả được chấp nhận.

Để tránh chờ các giao dịch khác phát hành khóa hàng, các tùy chọn

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4 và SELECT1 có thể được sử dụng với các câu lệnh đọc
# Session 1:

mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

mysql> INSERT INTO t (i) VALUES(1),(2),(3);

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+

# Session 2:

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.

# Session 3:

mysql> START TRANSACTION;

mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+
4 hoặc SELECT ... FOR SHARE.

  • SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    4

    Một lần đọc khóa sử dụng

    SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
    4 không bao giờ chờ để có được một khóa hàng. Truy vấn thực thi ngay lập tức, không bị lỗi nếu hàng được yêu cầu bị khóa.

  • SELECT1

    Một lần đọc khóa sử dụng SELECT1 không bao giờ chờ để có được một khóa hàng. Truy vấn thực thi ngay lập tức, loại bỏ các hàng bị khóa khỏi tập kết quả.

    Ghi chú

    Các truy vấn bỏ qua các hàng bị khóa trả về một cái nhìn không nhất quán của dữ liệu. Do đó, SELECT1 không phù hợp với công việc giao dịch nói chung. Tuy nhiên, nó có thể được sử dụng để tránh sự tranh chấp khóa khi nhiều phiên truy cập vào cùng một bảng giống như hàng đợi.

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4 và SELECT1 chỉ áp dụng cho các khóa cấp hàng.

Các tuyên bố sử dụng

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4 hoặc InnoDB2 không an toàn cho sao chép dựa trên câu lệnh.

Ví dụ sau đây cho thấy

SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4 và SELECT1. Phần 1 bắt đầu một giao dịch khóa một hàng trên một bản ghi duy nhất. Phần 2 thử một khóa đọc trên cùng một bản ghi bằng tùy chọn
SELECT * FROM t1 WHERE c1 = (SELECT c1 FROM t2 FOR UPDATE) FOR UPDATE;
4. Bởi vì hàng được yêu cầu bị khóa bởi Phần 1, việc đọc khóa trả về ngay lập tức với lỗi. Trong Phần 3, khóa đọc với InnoDB2 trả về các hàng được yêu cầu ngoại trừ hàng bị khóa trong Phần 1.

# Session 1:

mysql> CREATE TABLE t (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;

mysql> INSERT INTO t (i) VALUES(1),(2),(3);

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE;
+---+
| i |
+---+
| 2 |
+---+

# Session 2:

mysql> START TRANSACTION;

mysql> SELECT * FROM t WHERE i = 2 FOR UPDATE NOWAIT;
ERROR 3572 (HY000): Do not wait for lock.

# Session 3:

mysql> START TRANSACTION;

mysql> SELECT * FROM t FOR UPDATE SKIP LOCKED;
+---+
| i |
+---+
| 1 |
| 3 |
+---+

Chọn cập nhật trong MySQL là gì?

Chọn ... Để cập nhật đọc dữ liệu mới nhất có sẵn, đặt khóa độc quyền trên mỗi hàng mà nó đọc.Do đó, nó đặt cùng một khóa mà một bản cập nhật SQL được tìm kiếm sẽ đặt trên các hàng.reads the latest available data, setting exclusive locks on each row it reads. Thus, it sets the same locks a searched SQL UPDATE would set on the rows.

Làm cách nào để sử dụng Cập nhật Chọn?

Ví dụ: Chọn để cập nhật trong hành động Một giao dịch hoàn chỉnh sử dụng Chọn để cập nhật trên bảng đó có thể trông như thế này: Bắt đầu;Chọn * từ KV trong đó k = 1 để cập nhật;Cập nhật KV Set V = V + 5 trong đó K = 1;LÀM ;Làm việc theo dòng thông qua câu lệnh trên: dòng đầu tiên, bắt đầu, bắt đầu giao dịch.BEGIN; SELECT * FROM kv WHERE k = 1 FOR UPDATE; UPDATE kv SET v = v + 5 WHERE k = 1; COMMIT ; Working line by line through the statement above: The first line, BEGIN , initiates the transaction.

Chúng tôi có thể sử dụng cập nhật và chọn cùng nhau không?

Cấu trúc truy vấn, cập nhật từ Chọn chọn có thể được sử dụng để thực hiện loại kịch bản cập nhật dữ liệu này.Ngoài ra, chúng ta có thể sử dụng các câu lệnh hợp nhất thay thế và phương thức truy vấn con.. Also, we can use alternative MERGE statements and subquery methods.

MySQL có khóa một hàng để cập nhật không?

Để cập nhật: Bất kỳ khóa nào được đặt với `for update` sẽ không cho phép các giao dịch khác đọc, cập nhật hoặc xóa hàng.Giao dịch khác chỉ có thể đọc các hàng này khi giao dịch đầu tiên nhận được cam kết hoặc rollback.Any lock placed with the `FOR UPDATE` will not allow other transactions to read, update or delete the row. Other transaction can read this rows only once first transaction get commit or rollback.