Khóa MySQL trong khi TẠO BẢNG NHƯ CHỌN


10

Tôi đang chạy truy vấn (giả) sau đây

CREATE TABLE large_temp_table AS 
    SELECT a.*, b.*, c.* 
    FROM a
    LEFT JOIN b ON a.foo = b.foo
    LEFT JOIN c ON a.bar = c.bar

Giả sử truy vấn mất 10 phút để chạy. Cố gắng cập nhật giá trị trong các bảng a, b hoặc c trong khi nó đang chạy sẽ đợi truy vấn trên kết thúc trước. Tôi muốn tránh khóa này (tính nhất quán dữ liệu không được quan tâm). Làm thế nào tôi có thể đạt được điều đó?

Sử dụng: Bảng MySQL 5.1.41 và InnoDB

ps THIẾT LẬP CẤP PHÂN TÍCH GIAO DỊCH ĐỌC HIỂU; không mang lại sự thay đổi trong hành vi

Cập nhật Trong khi truy vấn đang được thực thi, đầu ra của SHOW Engine INNODB STATUS là như sau (mục đích của tôi là thực hiện một truy vấn rất chậm ở đây)

=====================================
120323 15:26:29 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 8 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 1470, signal count 1468
Mutex spin waits 0, rounds 7525, OS waits 112
RW-shared spins 803, OS waits 364; RW-excl spins 1300, OS waits 959
------------
TRANSACTIONS
------------
Trx id counter 0 3145870
Purge done for trx's n:o < 0 3141943 undo n:o < 0 0
History list length 22
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, OS thread id 2958192640
MySQL thread id 7942, query id 69073 localhost root
SHOW ENGINE INNODB STATUS
---TRANSACTION 0 3145869, ACTIVE 20 sec, OS thread id 2955325440, thread declared inside InnoDB 343
mysql tables in use 1, locked 1
6 lock struct(s), heap size 1024, 162 row lock(s)
MySQL thread id 7935, query id 69037 localhost root Copying to tmp table
CREATE TABLE 1_temp_foo AS
                       SELECT SQL_NO_CACHE
                           a.*
                       FROM
                           crm_companies AS a
                       LEFT JOIN users b ON a.zipcode = b.uid
                       LEFT JOIN calc_base_materials c ON a.zipcode = c.material_id
                       LEFT JOIN calc_base_material_langtext d ON a.zipcode = d.material_id
                       LEFT JOIN crm_people e ON a.zipcode = e.telephone1_number
                       ORDER BY a.country, a.name1
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
27579 OS file reads, 613 OS file writes, 392 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 5, seg size 7,
0 inserts, 0 merged recs, 0 merges
Hash table size 34679, node heap has 9 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 1 2030837110
Log flushed up to   1 2030837110
Last checkpoint at  1 2030837110
0 pending log writes, 0 pending chkp writes
231 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 21060366; in additional pool allocated 1048576
Dictionary memory allocated 2897304
Buffer pool size   512
Free buffers       0
Database pages     503
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 36022, created 166, written 504
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000
--------------
ROW OPERATIONS
--------------
1 queries inside InnoDB, 0 queries in queue
1 read views open inside InnoDB
Main thread id 2957578240, state: waiting for server activity
Number of rows inserted 2022, updated 7, deleted 13, read 528536
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 8.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

Cập nhật 2

Khi cố gắng cập nhật b, c hoặc d trong khi truy vấn đang chạy TÌNH TRẠNG TÌNH TRẠNG như sau:

=====================================
120323 16:12:58 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 27 seconds
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 2959, signal count 2957
Mutex spin waits 0, rounds 27587, OS waits 426
RW-shared spins 1321, OS waits 516; RW-excl spins 2578, OS waits 1855
------------
TRANSACTIONS
------------
Trx id counter 0 3145998
Purge done for trx's n:o < 0 3145994 undo n:o < 0 0
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 0 0, not started, OS thread id 2958602240
MySQL thread id 7990, query id 69621 localhost root
SHOW INNODB STATUS
---TRANSACTION 0 3145997, ACTIVE 35 sec, OS thread id 2955325440, thread declared inside InnoDB 227
mysql tables in use 1, locked 0
MySQL thread id 7984, query id 69594 localhost root Copying to tmp table
CREATE TABLE 1_temp_foo AS
                       SELECT SQL_NO_CACHE
                           a.*
                       FROM
                           crm_companies AS a
                       LEFT JOIN users b ON a.zipcode = b.uid
                       LEFT JOIN calc_base_materials c ON a.zipcode = c.material_id
                       LEFT JOIN calc_base_material_langtext d ON a.zipcode = d.material_id
                       LEFT JOIN crm_people e ON a.zipcode = e.telephone1_number
                       ORDER BY a.country, a.name1
Trx read view will not see trx with id >= 0 3145998, sees < 0 3145998
--------
FILE I/O
--------
I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)
Pending normal aio reads: 0, aio writes: 0,
ibuf aio reads: 0, log i/o's: 0, sync i/o's: 0
Pending flushes (fsync) log: 0; buffer pool: 0
54447 OS file reads, 1335 OS file writes, 509 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 5, seg size 7,
584 inserts, 584 merged recs, 4 merges
Hash table size 34679, node heap has 1 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 1 2060137545
Log flushed up to   1 2060137545
Last checkpoint at  1 2060137545
0 pending log writes, 0 pending chkp writes
338 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total memory allocated 20799534; in additional pool allocated 1047808
Dictionary memory allocated 2897304
Buffer pool size   512
Free buffers       0
Database pages     511
Modified db pages  0
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages read 70769, created 661, written 3156
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000
--------------
ROW OPERATIONS
--------------
1 queries inside InnoDB, 0 queries in queue
2 read views open inside InnoDB
Main thread id 2957578240, state: waiting for server activity
Number of rows inserted 2022, updated 66643, deleted 13, read 626517
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 7.59 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================

Và có danh sách quy trình mở thực tế

Danh sách quy trình

Câu trả lời:


10

Tôi thấy truy vấn này trong của bạn SHOW INNODB STATUS\G

CREATE TABLE 1_temp_foo AS 
                   SELECT SQL_NO_CACHE 
                       a.* 
                   FROM 
                       crm_companies AS a 
                   LEFT JOIN users b ON a.zipcode = b.uid 
                   LEFT JOIN calc_base_materials c ON a.zipcode = c.material_id 
                   LEFT JOIN calc_base_material_langtext d ON a.zipcode = d.material_id 
                   LEFT JOIN crm_people e ON a.zipcode = e.telephone1_number 
                   ORDER BY a.country, a.name1 

Truy vấn này cung cấp cho tôi creep vì nó kết hợp ba điều bạn có thể không nghĩ tới:

  • InnoDB được tham gia dựa trên tiền đề ban đầu của bạn: Using: MySQL 5.1.41 and InnoDB Tables
  • MyISAM cũng tham gia. Tại sao MyISAM có liên quan? TẤT CẢ CÁC BẢNG TEMP NỘI BỘ LÀ MyISAM !!! Kết quả tham gia là bảng MyISAM phải được chuyển đổi thành InnoDB khi bảng tạm thời đã được điền. Mức khóa mặc định cho các bảng MyISAM là gì? Khóa cấp bảng.
  • DDL có liên quan vì một bảng mới được tạo phải được đưa vào tồn tại. Bảng mới đó sẽ không được hiển thị cho đến khi bảng tạm thời được điền, chuyển đổi thành InnoDB và cuối cùng được đổi tên 1_temp_foo.

Có một tác dụng phụ khác đáng chú ý. Khi bạn làm

CREATE TABLE tblname AS SELECT ...

Bảng kết quả không có chỉ mục.

Tôi có một cái gì đó bạn có thể thấy hữu ích để bỏ qua vấn đề khóa. Nó liên quan đến việc tạo bảng đầu tiên dưới dạng một truy vấn riêng biệt, sau đó điền vào bảng. Có hai tùy chọn để tạo bảng tạm thời của bạn:

TÙY CHỌN # 1 : Thử tạo bảng có cùng bố cục

CREATE TABLE 1_temp_foo LIKE crm_companies;

Điều này sẽ tạo bảng 1_temp_foođể có các chỉ mục và công cụ lưu trữ chính xác giống như bảng gốc crm_companies.

TÙY CHỌN # 2 : Thử tạo bảng chỉ với cùng một công cụ lưu trữ, nhưng không có chỉ mục.

CREATE TABLE 1_temp_foo SELECT * FROM crm_companies WHERE 1=2;
ALTER TABLE 1_temp_foo ENGINE=InnoDB;

Sau khi tạo bảng (theo bất kỳ cách nào bạn chọn), bây giờ bạn có thể điền vào bảng như sau:

INSERT INTO 1_temp_foo
SELECT SQL_NO_CACHE a.*                   
FROM                   
    crm_companies AS a                   
    LEFT JOIN users b ON a.zipcode = b.uid                   
    LEFT JOIN calc_base_materials c ON a.zipcode = c.material_id                   
    LEFT JOIN calc_base_material_langtext d ON a.zipcode = d.material_id                   
    LEFT JOIN crm_people e ON a.zipcode = e.telephone1_number                   
    ORDER BY a.country, a.name
;

Bây giờ, truy vấn này sẽ tạo ra các khóa cấp hàng vì mục đích có sẵn dữ liệu để đọc lặp lại. Nói cách khác, đây là một truy vấn giao dịch.

CAUPAT

TÙY CHỌN # 2 có lợi thế hơn TÙY CHỌN # 1

  • Ưu điểm số 1 : Nếu crm_compiances có bất kỳ ràng buộc khóa ngoại nào, thì TÙY CHỌN # 1 là không thực sự có thể. Bạn sẽ phải chọn TÙY CHỌN # 2 vì đơn giản.
  • Ưu điểm # 2 : Vì TÙY CHỌN # 2 tạo một bảng không có chỉ mục do người dùng xác định, nên bảng sẽ tải nhanh hơn so với khi bảng được thực hiện qua TÙY CHỌN # 1.

2

Ngoài việc đặt mức cô lập giao dịch thành READ CAMITED (hoặc READ UNCOMMITTED), bạn cũng phải đặt định dạng nhật ký nhị phân của mình thành MIXED hoặc ROW. Bản sao dựa trên TUYÊN BỐ khóa loại tuyên bố này để đảm bảo mọi thứ đều "an toàn". Bạn cũng có thể tạm thời đặt innodb_locks_unsafe_for_binlog = 1, nhưng bạn có thể kết thúc với một nô lệ không đồng bộ theo cách đó.

SET binlog_format = ROW;
CREATE TABLE ... SELECT ...

Thật không may, điều này cũng không hoạt động :(
clops 23/03 '

1
Đầu ra của TÌNH TRẠNG SHOW Engine INNODB là gì khi câu lệnh CREATE TABLE đang chạy?
Aaron Brown

1
Ngoài ra, hãy chắc chắn rằng bạn đang sử dụng READ CAM KẾT, chứ không phải ĐỌC BẤT K .. Bạn có thể đang gặp phải lỗi này chưa được sửa cho đến 5.1.47 bug.mysql.com/orms.php?id=48607
Aaron Brown

1
Thật ki quặc. Có chìa khóa nước ngoài? Bạn có thể đăng TÌNH TRẠNG INNODB trong khi cố gắng cập nhật hàng không? Bạn đã thử điều này trên một phiên bản mới hơn của MySQL chưa? (tôi đoán là bạn đang sử dụng 5.1.41 vì nó giao hàng với bản phân phối của bạn?)
Aaron Brown

1
Bạn có chắc chắn rằng bảng người dùng của bạn là InnoDB? Bản cập nhật không xuất hiện trong đầu ra SHOW Engine INNODB STATUS và trong danh sách quy trình, nó xuất hiện dưới dạng Khóa, thông thường là kết quả của các bảng MyISAM. Tôi rất vui vì câu trả lời của @ RolandoMySQLDBA đã giải quyết vấn đề của bạn, nhưng tôi nghĩ có điều gì khác đang diễn ra ở đây.
Aaron Brown
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.