Board logo

標題: java database unique constraint問題 [打印本頁]

作者: twaiho2003    時間: 2016-2-14 23:49     標題: java database unique constraint問題

我係用spring data 的, 但係個問題都適用一般jdbc
我想問如果insert record果陣違反左unique constraint, 應該點樣由個exception搵返邊個field違反
我insert之前已經先check左有冇exist,  但係如果兩個thread 同時insert 同一款data, 就check唔到
到時就一定會error, 然後exception,
但係google左好耐都冇方法由個exception搵返邊個field.
作者: twaiho2003    時間: 2016-2-15 19:40

岩岩再google多陣,如果寫個@service
先check有冇exist, if no, insert, else return which field duplicate

Spring @service好似係single thread的
唔知咁樣得唔得呢?
作者: 望月小妖    時間: 2016-2-15 22:12

我唔識Spring,都難知邊個fields,Oracle就grep 個ORA-00001 exception 拆個constraint 名出嚟再query個 all_constraints / user_constraints table
作者: twaiho2003    時間: 2016-2-15 23:26

回覆 3# 望月小妖


    比著你會點handle insert account 果陣,username or email duplicate.
真係要寫regex拆個constraint name?
作者: alex959neth    時間: 2016-2-15 23:32

回覆 1# twaiho2003

Actually you may handle this kind of race condition properly by using Pessimistic locking or Optimistic Locking.

you may have a look:

http://stackoverflow.com/questio ... pring-and-hibernate
作者: mayday    時間: 2016-2-16 08:52

回覆  twaiho2003

Actually you may handle this kind of race condition properly by using Pessimistic ...
alex959neth 發表於 2016-2-15 23:32

好似只適合update,冇講insert得唔得。
作者: 望月小妖    時間: 2016-2-16 10:25

其實你用咩DBMS?用stored procedure check得唔得?
作者: tuyylihk    時間: 2016-2-16 10:31

本帖最後由 tuyylihk 於 2016-2-16 10:37 編輯

呢d野梗係用返sql解決,點會係java度解....

硬係要搞真係只可以係個exception抽返個field出黎
但我冇記錯架話exception好多時只係講第幾個field........

其實既然本身就有咁既考慮
不如乾脆係insert前先check入既野有冇撞現有data,同埋本身堆data有冇duplicate
===============================
噢岩岩見到multi-thread

但就又有個問題,你想點樣handle先
一個thread死就成個thread既野唔insert?
一個thread死只唔insert個一條?
commit point呢?

唔理咩方法都好,點都加返個lock會好d
你係咪真係要完全parallel insert?
作者: twaiho2003    時間: 2016-2-16 12:07

我用mysql, 如果用command line insert duplicate record
出Duplicate entry 'a' for key 'UK_979xvypjc2lwr1ia4kq77cko0'
Java exception 最有用果句getMessage()都係呢句
唔知PHP,PYTHON, .NET 各款mysql driver , 係咪都係return呢句?
唔知有冇一個error message 係programming friendly,

我覺得用java做任何checking都係重履, 我係mysql set左unique constraint,
佢內部已經會check
作者: rabbit82047    時間: 2016-2-17 22:26

本帖最後由 rabbit82047 於 2016-2-17 22:38 編輯

如果一定要用 thread 而又一定唔可以有 duplicate
你不如將 checking 同 insert 放入同一個 synchronized method 黎做好過
Performance 就唔好諗太多啦

Check exception 走遠路,俾我唔會向呢個方向諗

補充, phantom read 都要考慮,另一個方法就係 gen 完要 insert 既 data 統一做 checking 然後 batch insert
作者: alex959neth    時間: 2016-2-17 23:55

回覆 10# rabbit82047

Do you prefer synchronized method or using serializable transaction isolation for this problem, as suggested in this post?

http://forum.spring.io/forum/spr ... al-and-synchronized

Is there any circumstances of when to use each of them? Thanks.
作者: twaiho2003    時間: 2016-2-17 23:57

本帖最後由 twaiho2003 於 2016-2-17 23:58 編輯

回覆 10# rabbit82047


   我都諗過咁樣做,update insert delete呢d危險動作都係全部放同一個synchronized method,(1method per table).但等同將 database consistent個implementation搬左出java, Mysql咁多年研究既consistent優化,就因為個error message唔靚仔, 搞到我要用個咁簡陋public synchronized method
作者: 2014NUMBER    時間: 2016-2-18 03:10

n多年前試過用 mutex,semaphore handle concurrent ODBC,
java 就唔識
作者: 望月小妖    時間: 2016-2-18 09:26

本帖最後由 望月小妖 於 2016-2-18 09:29 編輯
不如乾脆係insert前先check入既野有冇撞現有data,同埋本身堆data有冇duplicate
tuyylihk 發表於 2016-2-16 10:31


要有 concurrency control
https://en.wikipedia.org/wiki/Non-lock_concurrency_control
作者: tuyylihk    時間: 2016-2-18 09:35

要有 concurrency control
望月小妖 發表於 2016-2-18 09:26

我睇到呀,唔駛理我前半段既野
作者: tuyylihk    時間: 2016-2-18 09:46

回覆  rabbit82047


   我都諗過咁樣做,update insert delete呢d危險動作都係全部放同一個synchronized  ...
twaiho2003 發表於 2016-2-17 23:57

有個蠢d既方法
既然你知道係unique key問題,出exception個陣再select返去搵
我冇記錯架話應該固定係SQLIntegrityConstraintViolationException

不過咁樣真係愈行愈遠....
作者: twaiho2003    時間: 2016-2-18 10:22

回覆 16# tuyylihk


    咁樣好似仲短左,原本用synchronized method, 每次都有check duplicate,
如果改做
try {
//insert
} catch(SQL...Exception e) {
//check which column
}

冇duplicate果d可以行少幾句

題外話:
寫JDBC driver果個有冇諗過將句error message , Duplicate entry 'a' for key 'UK_979xvypjc2lwr1ia4kq77cko0'改做
{"error":"duplicate","entry":"a","key":"UK_979xvypjc2lwr1ia4kq77cko0"} 或者
Duplicate 'a' UK_979xvypjc2lwr1ia4kq77cko0 或者
Duplicate,'a',UK_979xvypjc2lwr1ia4kq77cko0

我真係好想試下其他driver係咪咁, 最衰我唔識寫c,   佢個connecter/c應該最正宗
作者: tuyylihk    時間: 2016-2-18 10:57

本帖最後由 tuyylihk 於 2016-2-18 11:00 編輯
回覆  tuyylihk


    咁樣好似仲短左,原本用synchronized method, 每次都有check duplicate,
如果改做
t ...
twaiho2003 發表於 2016-2-18 10:22

係運行上係既
但老實講好唔建議係catch入面行D有可能會出exception既野...
作者: rabbit82047    時間: 2016-2-18 13:36

回覆  rabbit82047

Do you prefer synchronized method or using serializable transaction isolation fo ...
alex959neth 發表於 2016-2-17 23:55



synchronized method 最大問題係解決唔到 phantom read
要百份百安全就要將所有 db interaction 放入 sychronized method
但咁樣失去左 multi thread 既意義
唯一既好處可能就只係 database independent

serializable isolation level, 透過 database engine lock up 成個 table 安全好多
不過個 lock 會 hold 到 transaction commit, 效能影響應該都幾大
作者: twaiho2003    時間: 2016-2-18 14:32

回覆 19# rabbit82047


    我認為單純 read request 唔洗放入 synchronized method, 其他3種要, 雖然其他3種都有read statement做checking, 但因為其後動作係依照當時個select result 黎決定做定唔做,  所以select完唔可以再改動database,    直到做完
而單純read request 而冇即時動作,   例如網上訂iphone時, 我呢一刻見到仲有貨, 只可以係參考, 太多其他因素影響, 網絡傳送期間,  個record 可能已經被update
作者: alex959neth    時間: 2016-2-18 21:56

回覆 19# rabbit82047

According to my understanding, serializable isolation level hold a range lock for the search criteria (where clause) of the select query. That means when there is another transaction query the same table but do not have the search range overlapped with previous transaction, the query will not be blocked. Right?

http://dev.mysql.com/doc/refman/5.7/en/set-transaction.html

Also, I can think of another limitation for synchronized method. The synchronized method way may not suitable for environment that have multiple app server, right? or is there any solution to solve this case? Thanks.
作者: rabbit82047    時間: 2016-2-19 20:58

回覆 21# alex959neth


    Both statements are right.

我真係無諗過 multiple app server

咁樣或者 db 果 part 獨立出黎,透過 restful api expose 俾其他 app server
作者: rabbit82047    時間: 2016-2-19 21:07

回覆 20# twaiho2003


    之所以要將 read req 放埋入 synchronized method
就係要確保係 read 完之後唔會有其他 thread insert 同一個 record 入 db

e.g. Thread A & B
A: check for key abc (not exist) > B: check for key abc (not exists) > A: insert abc (synchronized) > B: insert abc (synchronized) << error





歡迎光臨 電腦領域 HKEPC Hardware (https://www.hkepc.com/forum/) Powered by Discuz! 7.2