1.在事務中使用查詢遇上併發的情況
(1)執行緒1事務開啟,執行緒2查詢資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒1:select * from t_a_tea where tea_id=1;
執行緒2:select * from t_a_tea where tea_id=1;
結果:bbb(tea_id=1時tea_name的資料)
結論:查詢不會觸發mysql共享鎖(讀鎖)
(2)執行緒1事務已開啟,執行緒1查詢資料,執行緒2修改資料,執行緒1讀取資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒1:select * from t_a_tea where tea_id=1;
執行緒2:update t_a_tea set tea_name=『ccc』 where tea_id=1;
執行緒1:select * from t_a_tea where tea_id=1;
結果:bbb(tea_id=1時tea_name的資料)
結論:查詢不會觸發mysql排他鎖(寫鎖),但是事務的隔離性會導致查詢到錯誤的資料
(3)執行緒1事務已開啟,執行緒2修改資料,執行緒1讀取資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒2:update t_a_tea set tea_name=『eee』 where tea_id=1;
執行緒1:select * from t_a_tea where tea_id=1;
結果:eee(tea_id=1時tea_name的資料)
結論:當資料沒有在事務中被執行sql語句時,不會觸發事務的隔離性,因此在事務中查詢不會得到錯誤的資料
(4)執行緒1事務已開啟,執行緒1修改資料,執行緒1讀取資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒1:update t_a_tea set tea_name=『eee』 where tea_id=1;
執行緒1:select * from t_a_tea where tea_id=1;
結果:eee(tea_id=1時tea_name的資料)
結論:在同乙個執行緒中不存在事務的隔離性,因此使用查詢操作不會得到錯誤的結果
2.在事務中使用更新遇上併發的情況
(1)執行緒1事務開啟,執行緒1更新資料,執行緒2更新資料,執行緒1提交資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒1:update t_a_tea set tea_name=『ccc』 where tea_id=1;
執行緒2:update t_a_tea set tea_name=『eee』 where tea_id=1;
執行緒1:commit;
結果:eee(tea_id=1時tea_name的資料)
結論:更新時觸發排他鎖(寫鎖),執行緒1執行完查詢執行緒2才繼續執行
(2)執行緒1事務開啟,執行緒1更新資料,執行緒2查詢資料
原始資料:tea_name=』bbb』;
執行緒1:start transaction;
執行緒1:update t_a_tea set tea_name=『ccc』 where tea_id=1;
執行緒2:select * from t_a_tea where tea_id=1;
結果:bbb(tea_id=1時tea_name的資料)
結論:更新時不會觸發共享鎖(讀鎖),事務的隔離性使執行緒1提交之前執行緒2查詢不到更新後的資料
3.在事務中使用插入遇上併發情況
因為插入語句不涉及已存在語句被鎖情況,因此測試當其中一條資料回滾時對主鍵id的影響
(1)執行緒1事務開啟,執行緒1新增一條資料,執行緒2新增一條資料,執行緒1回滾
新增一條資料,測試自增是否正常
insert into t_a_tea(tea_name) values (『qqq』);
此時資料狀態:
自增狀態正常,下一條主鍵狀態應為3
執行緒1:start transaction;
執行緒1:insert into t_a_tea(tea_name) values (『qqq』);
執行緒2:insert into t_a_tea(tea_name) values (『qqq』);
執行緒1:rollback;
執行緒2:commit;
結果:
結論:在事務沒有提交的情況下,事務中使用新增操作會影響主鍵id的自增,同理可得,當執行緒2開啟事務新增一條資料時使用回滾,會影響下一條資料的主鍵id
4.在事務中使用刪除遇上併發情況
(1)執行緒1開啟事務,執行緒1刪除tea_id=4的資料,執行緒2刪除tea_id=4資料
執行緒1:start transaction;
執行緒1:delete from t_a_tea where tea_id=4;
執行緒2:delete from t_a_tea where tea_id=4;
結果:執行緒2等待執行緒1提交後執行刪除操作
結論:刪除時會觸發事務的排他鎖(寫鎖)
(2)執行緒1開啟事務,執行緒1刪除tea_id=2的資料,執行緒2更新tea_id=2資料
執行緒1:start transaction;
執行緒1:delete from t_a_tea where tea_id=2;
執行緒2:update t_a_tea set tea_name=『eee』 where tea_id=2;
結果:執行緒2等待執行緒1提交後執行更新操作
結論:刪除時會觸發事務的排他鎖(寫鎖),且更新和刪除操作都受排他鎖影響
(3)執行緒1開啟事務,執行緒1刪除tea_id=2的資料,執行緒查詢tea_id=2資料
執行緒1:start transaction;
執行緒1:delete from t_a_tea where tea_id=2;
執行緒2:select * from t_a_tea where tea_id=2;
結果:
結論:刪除時不會觸發事務的共享鎖(讀鎖)
總結由測試結果可得:
1.當事務執行更新刪除時會觸發事務的排他鎖(寫鎖),是與之對應的資料無法進行更新刪除操作,但是不影響查詢操作,查詢的結果為未提交資料前的資料
2.當事務執行新增操作時,無論最後有無回滾,自增主鍵都會+1
3.當資料執行查詢操作時,由於事務的隔離性,當執行緒1使用查詢操作時觸發事務,不會觸發事務的排他鎖,此時執行緒2執行更新操作,執行緒1再查詢語句就會出現查詢不到執行緒2執行更新操作後的資料
可推測模型:
應用場景
限量搶購
錯誤案例:
表:t_a_shop,存放商品,當shop表中的num為0時,商品買完
//開啟事務
start transaction;
//獲取當前商品數
int shopnum = select num from t_a_shop where shop_id=?;
//得到應有商品數
shopnum -= shopnum;
//更新商品數
update t_a_shop set num=shopnum where shop_id=?
//提交事務
commit;
錯誤原因:當事務開啟時使用查詢並不會將shop_id=?的資料加排他鎖(寫鎖),因此在得到查詢結果時,其他執行緒還可以對資料進行更改,因此在事務提交時可能會使資料發生。
解決方式:update t_a_shop set num=num-1 where shop_id=?利用更新會加排他鎖的特性,保證事務的穩定執行
Mysql 邏輯架構 併發與事務
2 併發控制 3 事務 4 多版本併發控制 參考 每個客戶端連線都會在服務程序中擁有乙個執行緒,這個連線的查詢只會在這個單獨的執行緒找那個執行,該執行緒只能夠在某個cpu核心或者cpu中執行 對mysql進行查詢時,mysql會解析查詢,並建立內建資料介面 解析樹 然後對其進行各種優化 重寫查詢 決...
併發與事務
本部落格只是在開發過程中,對遇到的多執行緒問題的思考,如何在保證資料正確的前提下,提高效能。我覺得併發要考慮兩個問題 在io層次,併發鏈結數過多例如c10k,c10m的問題,是通過reactor 模式解決?例如開源的網路庫都是使用單執行緒io復用 非阻塞的思想解決,最優!還是通過乙個連線對應乙個執行...
事務與併發
一 首先我們先來看段 conn.setautocommit false int count1 utilconn.updatedata conn,update dict cost subj set is hr 0 if count1 1 else 這斷 經過資料庫跟蹤是 img set implici...