查看完整版本 : 這是否 MySQL 的 bug?

footballr 2017-2-8 10:32

公司有個 java program 會用來 update 部舊 Redhat server 的 MySQL 5.1.34, 運作多年一齊正常, 直至近月出現異常, 就係某一條 update SQL update 唔晒所有理應可以被 update 到既 records, 有部份會漏左. 於是嘗試用 SQL client 手動尋找原因, 發現以下奇怪現象:

1. select * from tableA where A & B; --> 5 rows fetched
2. update tableA set something=xxx where A & B; --> 2 rows updated
3. 隔左兩秒再行 (2) 條 update, 又多兩條被 update
4. 隔多兩秒再行 (2) 條 update, 最后一條才被 update

相同 where conditions 但唔能夠一次過 update 晒所有 records, 而由 (1) 至 (4) 那十秒八秒鐘又肯定背後冇 prorgram 轉個 tableA 既內容, restart 過 MySQL server 都係一樣, 請問有冇師兄有 idea 係乜問題呢? Thanks.

assembly.jc 2017-2-8 13:32

Records locked 吧。如果沒有記錯,MySQL 是 lock read 的,即另一個transaction 執行了select statement,在未有commit/rollback 前。selected records 是會鎖定的。

我的無比膏 2017-2-8 13:42

點解會覺得mysql 問題?問下自己改過啲咩先,有冇install patch

footballr 2017-2-8 14:47

[quote]原帖由 [i]assembly.jc[/i] 於 2017-2-8 01:32 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456034941&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
Records locked 吧。如果沒有記錯,MySQL 是 lock read 的,即另一個transaction 執行了select statement,在未有commit/rollback 前。selected records 是會鎖定的。 [/quote]

那個 tableA 是用 MyISAM engine 而不是 InnoDB engine, 以我所知並不支援 commit/rollback transaction. 而且那些先 select 確認 result set 再行 update 既動作在現存系統上我已行過無數次, 從未見過每次只能 update 部份 result set 既情況, 非常奇怪.

footballr 2017-2-8 14:54

[quote]原帖由 [i]我的無比膏[/i] 於 2017-2-8 01:42 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456035381&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
點解會覺得mysql 問題?問下自己改過啲咩先,有冇install patch [/quote]

因為整部 Redhat server 最近並沒有做過任何 update, 包括 MySQL server, 來來去去都係在同一個 DB 加減 table 和加減 record, 有諗過係咪自己邊個 step 出現人為錯誤, 但諗來諗去都諗唔到, 亦同 teammate 研究過, 可惜仍無任何頭緒.

[[i] 本帖最後由 footballr 於 2017-2-8 02:56 PM 編輯 [/i]]

assembly.jc 2017-2-9 19:48

[quote]原帖由 [i]footballr[/i] 於 2017-2-8 02:47 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456038685&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]


那個 tableA 是用 MyISAM engine 而不是 InnoDB engine, 以我所知並不支援 commit/rollback transaction. 而且那些先 select 確認 result set 再行 update 既動作在現存系統上我已行過無數次, 從未見過每次只能  ... [/quote]

對,MyISAM engine 不支援 commit/rollback transaction的,也因此會發生 partial update 的情況。看看以下例子。

[url=https://bugs.mysql.com/bug.php?id=57880]https://bugs.mysql.com/bug.php?id=57880[/url]


估計你每次執行 update statement,update 2 條 records 後就發生錯誤 (沒有 error message?),導致執行停止,但因 MyISAM 沒有 rollback,所以更新了的資料被保留。

form5 2017-2-10 00:07

myisamcheck 下table 同myi file 先

footballr 2017-2-10 11:52

[quote]原帖由 [i]assembly.jc[/i] 於 2017-2-9 07:48 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456112479&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
估計你每次執行 update statement,update 2 條 records 後就發生錯誤 (沒有 error message?),導致執行停止,但因 MyISAM 沒有 rollback,所以更新了的資料被保留。 [/quote]

其實我都係咁懷疑, 只係 select 晒相關 records 出來人眼望落去又正正常常, 兼且沒有 error message, 所以毫無頭緒, 以及唔知點樣可以防止日後再發生.

[[i] 本帖最後由 footballr 於 2017-2-10 11:56 AM 編輯 [/i]]

footballr 2017-2-10 11:54

[quote]原帖由 [i]form5[/i] 於 2017-2-10 12:07 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456124581&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
myisamcheck 下table 同myi file 先 [/quote]

行完 myisamchk 同 check table 都好似冇異樣.


[font=細明體][color=#ff0000][root@Server]# myisamchk -e -i /PATH/tableA.MYI[/color][/font]
[font=細明體]Checking MyISAM file: /PATH/tableA.MYI[/font]
[font=細明體]Data records: 1567255   Deleted blocks:       0[/font]
[font=細明體]- check file-size[/font]
[font=細明體]- check record delete-chain[/font]
[font=細明體]- check key delete-chain[/font]
[font=細明體]- check index reference[/font]
[font=細明體]- check data record references index: 1[/font]
[font=細明體]Key:  1:  Keyblocks used:  68%  Packed:    0%  Max levels:  4[/font]
[font=細明體]- check data record references index: 2[/font]
[font=細明體]Key:  2:  Keyblocks used:  99%  Packed:   93%  Max levels:  4[/font]
[font=細明體]- check data record references index: 3[/font]
[font=細明體]Key:  3:  Keyblocks used:  98%  Packed:  -11%  Max levels:  4[/font]
[font=細明體]Total:    Keyblocks used:  83%  Packed:   71%[/font]
[font=細明體][/font]
[font=細明體]- check records and index references[/font]
[font=細明體]Records:           1567255    M.recordlength:       77   Packed:            89%[/font]
[font=細明體]Recordspace used:      100%   Empty space:           0%  Blocks/Record:   1.00[/font]
[font=細明體]Record blocks:     1567255    Delete blocks:         0[/font]
[font=細明體]Record data:     120886033    Deleted data:          0[/font]
[font=細明體]Lost space:         561078    Linkdata:        6041885[/font]
[font=細明體][/font]
[font=細明體]User time 87.06, System time 0.26[/font]
[font=細明體]Maximum resident set size 0, Integral resident set size 0[/font]
[font=細明體]Non-physical pagefaults 18067, Physical pagefaults 0, Swaps 0[/font]
[font=細明體]Blocks in 0 out 0, Messages in 0 out 0, Signals 0[/font]
[font=細明體]Voluntary context switches 5, Involuntary context switches 409[/font]
[font=細明體][/font]
[font=細明體][color=#ff0000]mysql> check table tableA extended;[/color][/font]
[font=細明體]+----------------+-------+----------+----------+[/font]
[font=細明體]| Table          | Op    | Msg_type | Msg_text |[/font]
[font=細明體]+----------------+-------+----------+----------+[/font]
[font=細明體]| myDB.tableA    | check | status   | OK       |[/font]
[font=細明體]+----------------+-------+----------+----------+[/font]
[font=細明體]1 row in set (1 min 31.71 sec)[/font]

xianrenb 2017-2-10 12:37

[quote]原帖由 [i]footballr[/i] 於 2017-2-8 10:32 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456026074&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
公司有個 java program 會用來 update 部舊 Redhat server 的 MySQL 5.1.34, 運作多年一齊正常, 直至近月出現異常, 就係某一條 update SQL update 唔晒所有理應可以被 update 到既 records, 有部份會漏左. 於是嘗試用 ... [/quote]

會不會 A 、 B 有 SQL injection 的情況?
實際上又是什麼?
或者可以改用別的 field name 表示相同的 statement 貼上來,讓網友們了解多些。
另外 SQL 中用 “AND” 而不是 “&”,不過可能你只是在表示用上兩個 condition 來 “AND ”。

footballr 2017-2-10 12:48

[quote]原帖由 [i]xianrenb[/i] 於 2017-2-10 12:37 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456143157&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
會不會 A 、 B 有 SQL injection 的情況?
實際上又是什麼?
或者可以改用別的 field name 表示相同的 statement 貼上來,讓網友們了解多些。
另外 SQL 中用 “AND” 而不是 “&”,不過可能你只是在表示用上兩個 condition 來 “AND ”。 [/quote]

我想令條問題易睇 D 所以將 where columnA='A' and columnB='B' 縮寫成 where A & B.

我的無比膏 2017-2-10 13:36

你個數據量都唔少,行下execute plan, 睇下sql有冇問題,又或者開個nmon 睇下

assembly.jc 2017-2-12 22:44

[quote]原帖由 [i]footballr[/i] 於 2017-2-10 11:52 AM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456140860&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
以及唔知點樣可以防止日後再發生
[/quote]
對於一些 (如 MyISAM般) 沒有 atomic control 的 db engine,如果程式允許修改。可以考慮其他 work around 的方法。例如重覆執行 update statement,直至所有 records 都更新為止。考慮以下例子 (請自行轉回 java code)[code]n_not_updated NUMBER;

FOR i IN 1 .. 100 LOOP  // try 100 times        
    update  tableA
    set     something=XXX        
    where   A&B        
    and     something != XXX;

    select  count(*) into n_not_updated        
    from    tableA        
    where   A&B        
    and     something != XXX;               

    IF n_not_updated == 0 THEN               
        BREAK;   
    END IF;
END LOOP;

IF n_not_update > 0 THEN        
    LOG_ERROR("Records not fully updated");
END IF;       [/code]

footballr 2017-2-14 17:01

[quote]原帖由 [i]assembly.jc[/i] 於 2017-2-12 10:44 PM 發表 [url=http://computer.discuss.com.hk/redirect.php?goto=findpost&pid=456297924&ptid=26431984][img]http://computer.discuss.com.hk/images/common/back.gif[/img][/url]
對於一些 (如 MyISAM般) 沒有 atomic control 的 db engine,如果程式允許修改。可以考慮其他 work around 的方法。例如重覆執行 update statement,直至所有 records 都更新為止。考慮以下例子 (請自行轉回 java  ... [/quote]

多謝師兄提醒, 這確實是一個權宜之計, 可以暫時解決住先. :loveliness:
頁: [1]
查看完整版本: 這是否 MySQL 的 bug?