Bối cảnh: Khung được sử dụng là Spring và tất cả các truy vấn được chạy với JdbcTemplate. Phiên bản máy chủ Mysql là 5.6.19. Đây table
là một InnoDB table
và mặc định như auto commit
và mức cô lập lặp lại-đọc được đặt.
Vấn đề : Xảy Insert
ra bên trong một giao dịch và một select
dữ liệu đọc cùng một dữ liệu được chèn không nhìn thấy dữ liệu. Các select
chạy sau sự insert
và sau khi insert
giao dịch có commited
.
Tôi đã kích hoạt nhật ký bin cũng như nhật ký chung trong mysql. Nhật ký liên quan dưới đây
nhật ký bin:
SET TIMESTAMP=1438265764/*!*/;
BEGIN
/*!*/;
# at 249935389
#150730 14:16:04 server id 1 end_log_pos 249935606 CRC32 0xa6aca292 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265764/*!*/;
insert into user_geo_loc_latest(user_id, lat, lng) values(x,y,z) on duplicate key update lat=y, lng=z
/*!*/;
# at 249935606
#150730 14:16:06 server id 1 end_log_pos 249936255 CRC32 0x2a52c734 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table(txnid) VALUES ('885851438265675046')
/*!*/;
# at 249936255
#150730 14:16:06 server id 1 end_log_pos 249936514 CRC32 0x6cd85eb5 Query thread_id=40 exec_time=0 error_code=0
SET TIMESTAMP=1438265766/*!*/;
INSERT INTO table2(x) VALUES (y)
/*!*/;
# at 249936514
#150730 14:16:06 server id 1 end_log_pos 249936545 CRC32 0xceb9ec56 Xid = 9406873
COMMIT/*!*/;
Nhật ký truy vấn
150730 14:16:04 40 Query ...
....
40 Query select count(*) from table where txnid = '885851438265675046'
40 Query select @@session.tx_read_only
40 Query INSERT INTO table(txnid) VALUES ('885851438265675046')
40 Query select @@session.tx_read_only
40 Query INSERT INTO table2(x) values(y)
40 Query commit
....
150730 14:16:07 36 Query select pp.*, b.create_date from table pp left join bill b on pp.bill_id = b.bill_id where pp.txnid = '885851438265675046'
Thật kỳ lạ, Đầu tiên insert
(249935389) không nên là một phần của giao dịch. Đó là một lệnh gọi API riêng biệt và hoàn toàn không liên quan. Nó có thể là mùa xuân trộn nó với giao dịch hoặc tôi đang đọc nhật ký sai? AFAIK vì nó nằm trên cùng một chủ đề, nó ngụ ý chèn trong giao dịch.
Hai inserts
phần tiếp theo là một phần của giao dịch và có vẻ như nó cam kết. (249936514). Bây giờ truy vấn chọn (cuối cùng trong nhật ký chung) chạy sau cam kết và nó không thấy dữ liệu. Nó trả về 0 hàng. Làm thế nào điều này có thể xảy ra khi xem xét dữ liệu làcommitted
? Hoặc là commit
không phải trên chủ đề 40? Vì nó không có id chủ đề.
Để tóm tắt tôi có hai câu hỏi.
Có
BEGIN
trong binlog trướcINSERT INTO user_geo_loc
(không phải là một phần của giao dịch), đây có phải là lỗi với spring / Jdbc hoặc MySql chỉ đơn giản là làm điều này vì nó biết giao dịch này đã được cam kết (vì các giao dịch được ghi vào binlog khi chúng có đã thành công) và do đó sẽ không bao giờ được khôi phục.Đưa ra cam kết xảy ra trước khi chọn (cam kết là lúc 14:16:06 và chọn là lúc 14:16:07) làm thế nào mà lựa chọn không trả về hàng được chèn bởi giao dịch?
Điều này là vô cùng bối rối. Bất kỳ trợ giúp sẽ được đánh giá cao
Lưu ý: Các truy vấn trong cả bin và nhật ký truy vấn đã được chỉnh sửa để xóa thông tin nhạy cảm. Nhưng bản chất của các truy vấn vẫn giữ nguyên
Chỉnh sửa: Cập nhật với nhật ký chung và nhật ký truy vấn với một ví dụ chi tiết.
BEGIN
hoặc START TRANSACTION
. Bạn, thay vào đó, sử dụng autocommit=0
? (Tôi thích bắt đầu ... cam kết; nó làm cho phạm vi của giao dịch rõ ràng.)