mysql 事务 注意 优化_MySQL入门详解——事务、锁、优化
MySQL事務
MySQL 事務主要用于處理操作量大,復雜度高的數據。比如說,在一個商城系統中,用戶執行購買操作,那么用戶訂單中應該加一條,庫存要減一條,如果這兩步由于意外只進行了其中一步那么就會發生很大的問題。而事務可以很好的解決這個問題。
事務是數據庫處理操作,其中執行就好像它是一個單一的一組有序的工作單元。換言之在組內每個單獨的操作是成功的,那么一個事務才是完整的。如果事務中的任何操作失敗,整個事務將失敗。
事務性質:
原子性:確保工作單位中所有操作都成功完成;否則,事務被中止,在失敗時會回滾到事務操作以前的狀態。
一致性:可確保數據庫在正確的更改狀態進行一個成功的提交事務。
隔離性:使事務相互獨立的操作。
持久性:確保了提交事務的結果或系統故障情況下仍然存在作用。
TCL(事務控制語言):
begin;
操作;commit;
BEGIN或STARTTRANSACTION; #顯式地開啟一個事務COMMIT;或COMMIT WORK; #二者等階。COMMIT會提交事務并使已對數據庫進行的所有修改成為永久性的。未COMMIT的操作都存放在內存中,僅當前客戶端可以查看到,其他客戶端看不到,當前客戶端關閉后就清空了ROLLBACK;或ROLLBACK WORK; #二者等階。回滾會結束用戶的事務,并撤銷正在進行的所有未提交的修改SET AUTOCOMMIT=0#禁止自動提交 隱式開啟事務SET AUTOCOMMIT=1 #開啟自動提交
事務并發的問題:
1.臟讀:事務A讀取了事務B更新的數據,然后B回滾操作,那么A讀取到的數據是臟數據
2.不可重復讀:事務A多次讀取同一數據,事務B在事務A多次讀取過程中,對數據作了更新并提交 ,導致事務A多次讀取同一數據時結果不一致
3.幻讀:系統管理員A將數據庫中所有學生的成績從具體分數改為ABCDE等級,但是系統管理員B就在這個時候插入了一條具體分數的記錄,當系統管理員A改結束后發現還有一條沒有改過來,就好像 發生了幻覺一樣
各個隔離級別情況:
#查看隔離級別select @@session.tx_isolation;
#設置隔離級別set session transaction isolation level read uncommitted
隔離級別
臟讀可能性
不可重復讀可能性
幻讀可能性
未提交讀 READ UNCOMMITED
是
是
是
不可重復讀 READ COMMITED
否
是
是
可重復讀 REPEATABLE READ
否
否
是
串行化 SERIALIZABLE
否
否
否
數據庫鎖
mysql不同存儲引擎支持不同鎖機制,innodb支持表行級鎖默認行級鎖,memory采用表級鎖,bdb采用頁面鎖支持表級鎖。
表級鎖:開銷小,加鎖快,不會出現死鎖;鎖定粒度大,發生鎖沖突的概率最高,并發度最低。不支持事務。
頁面鎖:開銷和加鎖時間介于前后者之間,會出現死鎖;鎖定粒度介于前后者之間,并發度一般。
行級鎖:開銷大,加鎖慢,會出現死鎖;鎖定粒度小,發生鎖的沖突概率最低,并發度也最高。
表級鎖:兩種模式 共享鎖(讀鎖)與獨占鎖(寫鎖,排他鎖),表級鎖引擎:MyISAM MEMORY
共享鎖:在讀的時候上鎖,所有人都可以訪問不阻塞其他用戶對同一表讀請求,但阻塞同一表的寫操作包括自己;自己如果加了讀鎖,更新訪問其他表會提示錯誤;加了讀鎖之后不能再加寫鎖
獨占鎖:上鎖之后其他人不能訪問,阻塞其他用戶對同一表的讀和寫操作,獨占鎖優先級別高于共享鎖;自己加了寫鎖可以讀寫表中記錄,但更新訪問其他表都會提示錯誤
MyISAM在執行查詢語句時會自動給涉及的所有表加讀鎖,在執行更新操作前加寫鎖,這個過程一般不需要用戶干預。
#加鎖
lock tables table_nameread [local];lock tables table_name write [local];
#多表加鎖
lock tables table_name[table_name] read [local];lock tables table_name [table_name] write [local];
#釋放鎖
unlock tables;
#查詢表級鎖爭用情況
show statuslike 'table%';
show statuslike '%lock%';當waited immediate值比較大是說明阻塞嚴重
show processlist; #查看哪些sql在在等待鎖
showopentables; #當前被鎖住的表以及鎖的次數
#并發插入
myisam存儲引擎有一個系統變量concurrent_insert.專門用以控制其并發插入行為,其值為NEVER0、AUTO1(默認)、ALAWAYS2。0:不允許并發插入 ,1:如果表中沒有空洞(表中沒有被刪除的行)myisam允許在一個進程讀表的同時,另一個進程從表尾插入記錄,2:無論表中有沒有空洞,都允許在表尾插入記錄
#讀寫鎖優先級
max_write_lock_count=1#設置寫鎖的最多次數,當系統處理一個寫操作后就會暫停寫操作給讀操作執行機會
#降低寫操作優先級,給讀操作更高優先級
low_priority_updates=1 sql_low_priority_updates=1 在用寫操作時要加low_priority關鍵字#視場景而定,讀場景更重要或更多時如此設置
如何優化表所?
concurrent_insert設置2,總是允許并發插入,但是要定期OPTIMIZE TABLE整理空間碎片;視情況設置寫優先級;視情況設置寫內存,解決批量插入數據(如新聞系統更新)場景中。
行級鎖:引擎InnoDB,模式包含 共享鎖(S),排它鎖(X),意向共享鎖(IS),意向排它鎖(IX) 如果一個事務請求的鎖模式與當前的鎖兼容,innoDB就將請求的鎖授予該事物;反之,如果兩者不兼容,該事物就要等待鎖釋放
行級鎖特點:innoDB行鎖是通過給索引上的索引項加鎖來實現的,只有通過索引條件(例如id)檢索數據,innoDB才使用行級鎖,佛則將使用表鎖;意向鎖是innoDB自動加的,不需要用戶干預,對于寫操作(insert update delete)innodb會自動給涉及數據加排它鎖,對于select InnoDB不會加任何鎖
排它鎖(X)意向排它鎖(IX)共享鎖(S)意向共享鎖(IS)
排它鎖(X)
沖突
沖突
沖突
沖突
意向排它鎖(IX)
沖突
兼容
沖突
兼容
共享鎖(S)
沖突
沖突
兼容
兼容
意向共享鎖(IS)
沖突
兼容
兼容
兼容
#加鎖SELECT * FROM table_name WHERE ... LOCK INSHARE MODE #主動添加共享鎖(S)SELECT * FROM table_name WHERE ... FOR UPDATE#主動添加獨占鎖(X)
#釋放鎖commit;或rollback;
當使用行排他鎖寫數據時,其他人無法操作本條數據;
當給一條數據添加了排它鎖,其他人對這條數據沒有任何權限,但并不影響其他人對其他數據操作;
在InnoDB默認的隔離方式下,操作者不提交,操作數據只保存在內存里,另一用戶可以查詢,查詢到的是舊值;
即使字段家里索引在使用時自己變了類型,索引失效會加表鎖;
間隙鎖:比如有124三個數據,操作>1的數據,此時添加3或者5都是不可以的,所以要明確范圍防止間隙鎖
如何優化行級鎖:
盡量使用較低的隔離級別(新手忽略);精心設計索引,并盡量使用索引訪問數據,使加鎖更精確從而減少鎖沖突的機會
選擇合理的事務大小,小事務發生鎖沖突的幾率也小
給記錄集手動加鎖時,最好一次性請求足夠級別的鎖
盡量使用相等條件訪問數據,這樣可以避免間隙鎖對并發插入的影響
對于一些特定事務,可以使用表鎖提高速度并減少死鎖可能
數據庫優化操作
優化成本 硬件>系統配置>數據庫表結構>SQL語句及索引
優化效果 SQL語句及索引
MySQL邏輯架構:
客戶端->連接線程處理->查詢緩存、分析器、優化器->存儲引擎
索引底層實現:B樹
myisam存儲是數據的地址 innodb存儲的是索引值,所以索引不宜過長
explain參數詳解:
select語句執行順序:執行順序:先where...group by ... having 再 select ... from ... 再 distinct ... order by ... limit ...
#使用方式:
explainselect * fromdemo;
#參數:
#id 執行順序
id相同時順序從被查詢表數據量少至多(都一樣的話按照書寫順序),子查詢時id由外到里自增,先執行大的
#select_type 查詢中每個select子句的類型
SIMPLE:簡單SELECT(不使用UNION或子查詢)PRIMARY:最外面的SELECTUNION:UNION中的第二個或后面的SELECT語句
DEPENDENTUNION:UNION中的第二個或后面的SELECT語句,取決于外面的查詢UNION RESULT:UNION的結果
SUBQUERY:子查詢中的第一個SELECT
DEPENDENT SUBQUERY:子查詢中的第一個SELECT,取決于外面的查詢
DERIVED:派生表(FROM子句的子查詢)
#table本次查詢的表名,或派生表
#type mysql在表中的訪問類型ALL: 遍歷全表,目標不帶索引<
index: 遍歷全表索引樹,不能用in會使索引失效
NULL#possible_keys 本查詢可能用的索引
#key本查詢真實用的索引
#key_len 索引在內存中占的長度(輕易不要給varchar加索引)
#ref 指定的條件類型
#rows 當前語句查到的行數
#ExtraDistinct:MySQL發現第1個匹配行后,停止為當前的行組合搜索更多的行。Not exists:MySQL能夠對查詢進行LEFT JOIN優化,發現1個匹配LEFT JOIN標準的行后,不再為前面的的行組合在該表內檢查更多的行。
range checkedfor each record (indexmap: ):MySQL沒有發現好的可以使用的索引,但發現如果來自前面的表的列值已知,可能部分索引可以使用。
Using filesort:MySQL需要額外的一次傳遞,以找出如何按排序順序檢索行。
Usingindex:從只使用索引樹中的信息而不需要進一步搜索讀取實際的行來檢索表中的列信息,代表性能不錯
Usingtemporary:為了解決查詢,MySQL需要創建一個臨時表來容納結果。
Usingwhere:WHERE子句用于限制哪一個行匹配下一個表或發送到客戶,性能一般
Using sort_union(...), Usingunion(...), Using intersect(...):這些函數說明如何為index_merge聯接類型合并索引掃描。
Usingindex for group-by:類似于訪問表的Using index方式,Using index for group-by表示MySQL發現了一個索引,可以用來查 詢GROUP BY或DISTINCT查詢的所有列,而不要額外搜索硬盤訪問實際的表。
IMPOSSIBLE :不可能的where語句如where id=1 and id=2
mysql優化方法:
1.通過使用explain命令分析sql語句的運行效率
2.通過開啟慢查詢日志查看效率慢的sql語句
單多表sql優化手段:
給使用頻繁的字段加索引,調整索引順序最佳左前綴原則,刪除多余干擾索引,調整查詢條件對索引有干擾的語句放最后
多表sql額外優化手段:
1.小表驅動大表(小表在左邊,where小表.x=大表.y)
2.left join 給左邊表加索引,right join 給右邊表加索引
注意:
1.不要將索引作為函數參數或表達式的一部分,這樣會讓索引失效;索引不要進行類型轉化否則失效
2.復合索引應該遵循最佳左前綴,不要用or,in,!= < >關鍵字否則失效
3.及時刪除冗長,不常用的索引
4.like查詢時盡量不要使用左邊%引起索引失效
系統級別優化:
主從復制,讀寫分離,負載均衡
其他優化:
選盡量小的數據類型,列設置not null,加unsigned不允許加正負這樣可以使正數上線多一倍,存儲時間最好用TIMESTAMP使用4個字節存儲,大多數情況下沒有枚舉類型的必要,表的列不要太不要超過10個字段多影響內存數據類型小而簡單
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的mysql 事务 注意 优化_MySQL入门详解——事务、锁、优化的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一千块的电脑靠谱吗有一千块钱的电脑吗
- 下一篇: 月经日期怎么算