其實這個和jsp沒啥關系,只要你的代碼沒有比如爆源碼或者直接上傳shell這些弱智的漏洞就行了,一般的做法其實很簡單,就是給mysql分配一個單獨的賬號,而不要使用root權限,而且只能針對目標數(shù)據(jù)庫操作,其他的數(shù)據(jù)庫沒有操作權限,如果要附加上jsp的話,那么就是別讓你的程序出現(xiàn)注入之類的漏洞,因為只要存在注入,那么至少可以肯定你的數(shù)據(jù)庫會全部泄露,這樣會使別人進一步入侵你甚至控制你的服務器,當然了linux和windows的服務器還是有差別的,上面給你說的只是最一般的方法
成都創(chuàng)新互聯(lián)服務項目包括臨川網(wǎng)站建設、臨川網(wǎng)站制作、臨川網(wǎng)頁制作以及臨川網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,臨川網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到臨川省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
mysql不支持 嵌入式的sql 所以 你的要求不能實現(xiàn)了。
不過可以在程序?qū)訉崿F(xiàn)的
偽代碼:
start transacation
select 庫存 from 庫存表
if ($購買數(shù)量庫存)
echo “error”
else
insert 出庫單 xxxxxx
update 庫存
commit
看數(shù)據(jù)庫中的字段的設計,一般設置為數(shù)值即可保存負值,也可以用文字段保存,取出后自行轉(zhuǎn)換成數(shù)字即可。
1、首先最上面會查詢當前的剩余庫存(可能不準確,但沒關系,這里只是第一步粗略校驗)。
2、其次前置校驗,若已經(jīng)沒有庫存,前置攔截生效。
3、最后即可減少對數(shù)據(jù)庫的寫操作,畢竟讀操作不涉及加鎖,并發(fā)性能高。
想要知道如何處理數(shù)據(jù)并發(fā),自然需要先了解數(shù)據(jù)并發(fā)。
什么是數(shù)據(jù)并發(fā)操作呢?
就是同一時間內(nèi),不同的線程同時對一條數(shù)據(jù)進行讀寫操作。
在互聯(lián)網(wǎng)時代,一個系統(tǒng)常常有很多人在使用,因此就可能出現(xiàn)高并發(fā)的現(xiàn)象,也就是不同的用戶同時對一條數(shù)據(jù)進行操作,如果沒有有效的處理,自然就會出現(xiàn)數(shù)據(jù)的異常。而最常見的一種數(shù)據(jù)并發(fā)的場景就是電商中的秒殺,成千上萬個用戶對在極端的時間內(nèi),搶購一個商品。針對這種場景,商品的庫存就是一個需要控制的數(shù)據(jù),而多個用戶對在同一時間對庫存進行重寫,一個不小心就可能出現(xiàn)超賣的情況。
針對這種情況,我們?nèi)绾斡行У奶幚頂?shù)據(jù)并發(fā)呢?
第一種方案、數(shù)據(jù)庫鎖
從鎖的基本屬性來說,可以分為兩種:一種是共享鎖(S),一種是排它鎖(X)。在MySQL的數(shù)據(jù)庫中,是有四種隔離級別的,會在讀寫的時候,自動的使用這兩種鎖,防止數(shù)據(jù)出現(xiàn)混亂。
這四種隔離級別分別是:
讀未提交(Read Uncommitted)
讀提交(Read Committed)
可重復讀(Repeated Read)
串行化(Serializable)
當然,不同的隔離級別,效率也是不同的,對于數(shù)據(jù)的一致性保證也就有不同的結果。而這些可能出現(xiàn)的又有哪些呢?
臟讀(dirty read)
當事務與事務之間沒有任何隔離的時候,就可能會出現(xiàn)臟讀。例如:商家想看看所有的訂單有哪些,這時,用戶A提交了一個訂單,但事務還沒提交,商家卻看到了這個訂單。而這時就會出現(xiàn)一種問題,當商家去操作這個訂單時,可能用戶A的訂單由于部分問題,導致數(shù)據(jù)回滾,事務沒有提交,這時商家的操作就會失去目標。
不可重復讀(unrepeatable read)
一個事務中,兩次讀操作出來的同一條數(shù)據(jù)值不同,就是不可重復讀。
例如:我們有一個事務A,需要去查詢一下商品庫存,然后做扣減,這時,事務B操作了這個商品,扣減了一部分庫存,當事務A再次去查詢商品庫存的時候,發(fā)現(xiàn)這一次的結果和上次不同了,這就是不可重復讀。
幻讀(phantom problem)
一個事務中,兩次讀操作出來的結果集不同,就是幻讀。
例如:一個事務A,去查詢現(xiàn)在已經(jīng)支付的訂單有哪些,得到了一個結果集。這時,事務B新提交了一個訂單,當事務A再次去查詢時,就會出現(xiàn),兩次得到的結果集不同的情況,也就是幻讀了。
那針對這些結果,不同的隔離級別可以干什么呢?
“讀未提(Read Uncommitted)”能預防啥?啥都預防不了。
“讀提交(Read Committed)”能預防啥?使用“快照讀(Snapshot Read)”方式,避免“臟讀”,但是可能出現(xiàn)“不可重復讀”和“幻讀”。
“可重復讀(Repeated Red)”能預防啥?使用“快照讀(Snapshot Read)”方式,鎖住被讀取記錄,避免出現(xiàn)“臟讀”、“不可重復讀”,但是可能出現(xiàn)“幻讀”。
“串行化(Serializable)”能預防啥?有效避免“臟讀”、“不可重復讀”、“幻讀”,不過運行效率奇差。
好了,鎖說完了,但是,我們的數(shù)據(jù)庫鎖,并不能有效的解決并發(fā)的問題,只是盡可能保證數(shù)據(jù)的一致性,當并發(fā)量特別大時,數(shù)據(jù)庫還是容易扛不住。那解決數(shù)據(jù)并發(fā)的另一個手段就是,盡可能的提高處理的速度。
因為數(shù)據(jù)的IO要提升難度比較大,那么通過其他的方式,對數(shù)據(jù)進行處理,減少數(shù)據(jù)庫的IO,就是提高并發(fā)能力的有效手段了。
最有效的一種方式就是:緩存
想要減少并發(fā)出現(xiàn)的概率,那么讀寫的效率越高,讀寫的執(zhí)行時間越短,自然數(shù)據(jù)并發(fā)的可能性就變小了,并發(fā)性能也有提高了。
還是用剛才的秒殺舉例,我們?yōu)榈木褪潜WC庫存的數(shù)據(jù)不出錯,賣出一個商品,減一個庫存,那么,我們就可以將庫存放在內(nèi)存中進行處理。這樣,就能夠保證庫存有序的及時扣減,并且不出現(xiàn)問題。這樣,我們的數(shù)據(jù)庫的寫操作也變少了,執(zhí)行效率也就大大提高了。
當然,常用的分布式緩存方式有:Redis和Memcache,Redis可以持久化到硬盤,而Memcache不行,應該怎么選擇,就看具體的使用場景了。
當然,緩存畢竟使用的范圍有限,很多的數(shù)據(jù)我們還是必須持久化到硬盤中,那我們就需要提高數(shù)據(jù)庫的IO能力,這樣避免一個線程執(zhí)行時間太長,造成線程的阻塞。
那么,讀寫分離就是另一種有效的方式了
當我們的寫成為了瓶頸的時候,讀寫分離就是一種可以選擇的方式了。
我們的讀庫就只需要執(zhí)行讀,寫庫就只需要執(zhí)行寫,把讀的壓力從主庫中分離出去,讓主庫的資源只是用來保證寫的效率,從而提高寫操作的性能。