mysql查看被鎖住的表
mysql查看被鎖住的表
查詢是否鎖表
show OPEN TABLES where In_use > 0;
查看所有進程
MySQL:
show processlist;
mariabd:
show full processlist;
查詢到相對應的進程===然后 kill id
殺掉指定mysql連接的進程號
kill $pid
查看正在鎖的事務
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
查看等待鎖的事務
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
查看innodb引擎的運行時信息
show engine innodb status\G;
查看造成死鎖的sql語句,分析索引情況,然后優化sql語句;
查看服務器狀態
show status like '%lock%';
查看超時時間:
show variables like '%timeout%';
sql優化方式
1.查詢數據庫的數據盡量使用索引來查詢,避免全表掃描。盡量只查詢索引條件的字段,
例如,一張名為user用戶數據表的id字段為索引,name字段為用戶,為非索引字段,
當查詢某條數據時,只查詢id比查詢name效率會高很多。
因為葉子節點存儲索引值(id)的值,這樣不會回表查詢,實現了索引覆蓋。
2.從數據庫中查詢數據,sql語句盡量避免使用or來連接條件查詢。
因為使用or會導致執行sql的時候進行范圍的索引掃描或則全表查詢,效率降低。
例如,select id from user wehere name='a' or name='b',
可以改為以下的形式來提高查詢的效率:
select id from user wehere name='a'
union
select id from user wehere name='b'
3.在連續數組的查詢中,能使用between的情況下,盡量使用between,而不使用in。in和not in可能會導致全表查詢
4.sql語句的where查詢條件,對字段進行表達式操作,會導致mysql引擎放棄使用索引而進行全表掃描。
例如,select * from user where age/2=10(age字段有索引,在where中盡量不要進行表達式操作)
5.sql語句的where查詢條件,對字段進行函數操作,也會導致mysql引擎放棄使用索引而進行全表掃描查詢。
例如,select name from user where substr(name,2,3)='tom'
6.多張數據表查詢數據,使用inner join,left/right join來替代子查詢。
因為子查詢需要在內存中創建臨時表,來完成這個邏輯上的需要兩個步驟的查詢工作。(創建臨時表也有可能會降低效率)
7. in()適合B表比A表數據小的情況,
exists()適合B表比A表數據大的情況,
例如,select name from user a where exists(select name from user b where a.id=19) 和
select name from user a where id in(select name from user b where b.id=19)
8.在使用like進行數據表的查詢時,能用單%的情況下,不建議使用雙%,
雙%查詢會導致mysql引擎放棄使用索引而進行全表掃描查詢,查詢時盡量把%放后面,或者不使用%。
9.在mysql建立聯合索引時會遵循最左前綴匹配的原則,即最左優先,在檢索數據時從聯合索引的最左開始匹配。
左邊匹配不到,整個sql不走索引。
例如,select name from user where u_one='1' and u_two='2'
(如果第一個沒找到,不走索引,那么后面也不會走索引,即最左優先)
10.從數據庫中查詢數據時候,使用精確的類型匹配。
比如, select id from user wehere id='3' 如果id建立的varchar類型的走索引,
如果寫成 select id from user wehere id=3 不走索引
11.選取最適應的字段屬性,一般說來,數據庫中的表越小,執行的查詢也就會越快。
因此,在創建表的時候,為了獲得更好的性能,我們可以將表中字段的寬度設得盡可能小
另外一個提高效率的方法是在可能的情況下,應該盡量把字段設置為not null,
這樣在將來執行查詢的時候,數據庫不用去比較null的值。
12.數據量比較大時,合理使用分區表。使用partition by 子句定義每個分區存放的數據。
在執行查詢的時候,優化器會根據分區定義過濾哪些沒有我們需要數據的分區,
這樣查詢就無需掃描所有分區,只需要查詢包含需要數據的分區就可以了。
13.合理選擇存儲引擎。
lnnodb: 適合數據完整性,並發性處理,擅長更新,刪除。
myisam: 適合高速查詢及插入。擅長插入和查詢。
14.慢查詢日志的使用,在調試的時候開啟慢查詢,定位的慢查詢語句,再做優化策略。
關閉/開啟語句 slow_query_log=0|1,
超出該時間臨界點,就為慢查詢 long_query_time=N
mysql 為什么采用B+樹作為索引的數據結構
索引本身數據量也很大,不可能全部存儲在內存中,因此索引往往以索引文件的形式存儲的磁盤上。
這樣的話,索引查找過程中就要產生磁盤I/O消耗,相對於內存存取,I/O存取的消耗要高幾個數量級,
所以索引的結構組織要盡量減少查找過程中磁盤I/O的存取次數,提升索引效率。
常用的索引類型:
順序查找: 最基本的查詢算法-復雜度O(n),大數據量此算法效率糟糕。
二叉樹查找(binary tree search): O(log2n),對於某些情況,二叉查找樹會退化成一個有n個節點的線性鏈,和順序查找差不多。顯然這個二叉樹的查詢效率就很低。
hash索引: 哈希索引基於哈希表實現,只有精確匹配索引所有列的查詢才有效,無法滿足范圍查找。
紅黑樹: 一種平衡二叉樹,一個節點只能有左子樹和右子樹,導致樹高度非常高,邏輯上很近的節點(父子)物理上可能很遠,
無法利用局部性,IO次數多查找慢,效率低。邏輯上相鄰節點沒法直接通過順序指針關聯,可能需要迭代回到上層節點重復向下遍歷找到對應節點,效率低
B Tree: B-TREE 每個節點都是一個二元數組: [key, data],所有節點都可以存儲數據。key為索引,data為數據。
檢索原理:首先從根節點進行二分查找,如果找到則返回對應節點的data,否則對相應區間的指針指向的節點遞歸進行查找,直到找到節點或未找到節點返回null指針。
缺點: 1.插入刪除新的數據記錄會破壞B-Tree的性質,因此在插入刪除時,需要對樹進行一個分裂、合並、轉移等操作以保持B-Tree性質。造成IO操作頻繁。
2.區間查找可能需要返回上層節點重復遍歷,IO操作繁瑣。
B+Tree: B Tree的變種
與B Tree相比,B+Tree有以下不同點:非葉子節點不存儲data,只存儲索引key;只有葉子節點才存儲data
Mysql中B+Tree:在經典B+Tree的基礎上進行了優化,增加了順序訪問指針。
在B+Tree的每個葉子節點增加一個指向相鄰葉子節點的指針,就形成了帶有順序訪問指針的B+Tree。這樣就提高了區間訪問性能
2、B+樹索引的性能優勢:
1)、結合操作系統存儲結構優化處理: mysql巧妙運用操作系統存儲結構(一個節點分配到一個存儲頁中->盡量減少IO次數) & 磁盤預讀(緩存預讀->加速預讀馬上要用到的數據)。
2)、B+樹單個節點能放多個子節點,相同IO次數,檢索出更多信息。
3)、B+樹只在葉子節點存儲數據 & 所有葉子結點包含一個鏈指針 & 其他內層非葉子節點只存儲索引數據。只利用索引快速定位數據索引范圍,先定位索引再通過索引高效快速定位數據。
B+樹的優勢:
因為B+樹沒有與內部節點相關聯的數據,所以在內存頁面上可以容納更多的鍵。因此,訪問葉子節點上的數據需要更少的緩存丟失。
B+樹的葉節點是鏈接的,因此對樹中的所有對象進行全面掃描只需要一個線性遍歷所有葉節點。另一方面,B樹需要遍歷樹中的每一層。這種全樹遍歷可能比B+葉子的線性遍歷涉及更多的緩存丟失。
B樹的優勢:
因為B樹包含每個鍵的數據,所以經常訪問的節點可以更靠近根,因此可以更快地訪問。
mysql 數據庫的索引類型有哪些
使用索引可以大大提高MySQL的檢索速度,但是也會降低更新表的速度,索引雖好可不要貪多哦。
有哪些索引可供選擇呢?
1、普通索引
最基本的索引,它沒有任何限制,用於加速查詢。
創建方法:
a. 建表的時候一起創建
CREATE TABLE mytable ( name VARCHAR(32) , INDEX index_mytable_name (name) );
b. 建表后,直接創建索引
CREATE INDEX index_mytable_name ON mytable(name);
c. 修改表結構
ALTER TABLE mytable ADD INDEX index_mytable_name (name);
注:如果是字符串字段,還可以指定索引的長度,在列命令后面加上索引長度就可以了(例如:name(11))
2、唯一索引
索引列的值必須唯一,但允許有空值。如果是組合索引,則列值的組合必須唯一。
創建方法:
a. 建表的時候一起創建
CREATE TABLE mytable ( `name` VARCHAR(32) , UNIQUE index_unique_mytable_name (`name`) );
b. 建表后,直接創建索引
CREATE UNIQUE INDEX index_mytable_name ON mytable(name);
c. 修改表結構
ALTER TABLE mytable ADD UNIQUE INDEX index_mytable_name (name);
注:如果是字符串字段,還可以指定索引的長度,在列命令后面加上索引長度就可以了(例如:name(11))
3、主鍵索引
是一種特殊的唯一索引,一個表只能有一個主鍵,不允許有空值。一般是在建表的時候同時創建主鍵索引。
創建方法:
a. 建表的時候一起創建
CREATE TABLE mytable ( `id` int(11) NOT NULL AUTO_INCREMENT , `name` VARCHAR(32) , PRIMARY KEY (`id`) );
b. 修改表結構
ALTER TABLE test.t1 ADD CONSTRAINT t1_pk PRIMARY KEY (id);
注:如果是字符串字段,還可以指定索引的長度,在列命令后面加上索引長度就可以了(例如:name(11))
4、組合索引
指多個字段上創建的索引,只有在查詢條件中使用了創建索引時的第一個字段,索引才會被使用。使用組合索引時遵循最左前綴集合。
創建方法:
a. 建表的時候一起創建
CREATE TABLE mytable ( `id` int(11) , `name` VARCHAR(32) , INDEX index_mytable_id_name (`id`,`name`) );
b. 建表后,直接創建索引
CREATE INDEX index_mytable_id_name ON mytable(id,name);
c. 修改表結構
ALTER TABLE mytable ADD INDEX index_mytable_id_name (id,name);
5、全文索引
主要用來查找文本中的關鍵字,而不是直接與索引中的值相比較。
fulltext索引跟其它索引大不相同,它更像是一個搜索引擎,而不是簡單的where語句的參數匹配。
fulltext索引配合match against操作使用,而不是一般的where語句加like。
實際使用較少。
【拓展】、哪些情況需要創建索引
1、主鍵自動建立唯一索引
2、頻繁作為查詢條件的字段應該創建索引(where 后面的語句)
3、查詢中與其它表關聯的字段,外鍵關系建立索引
4、查詢中排序的字段,排序字段若通過索引去訪問將大大提高排序速度
5、查詢中統計或者分組字段
(6)、哪些情況不要創建索引
1、表記錄太少
2、經常增刪改的表:提高了查詢速度,同時卻會降低更新表的速度,如對表進行INSERT、UPDATE和DELETE。 因為更新表時,MySQL不僅要保存數據,還要保存一下索引文件
3、Where條件里用不到的字段不創建索引
4、數據重復且分布平均的表字段,某個數據列包含許多重復的內容,建立索引沒有太大實際效果。
mysql 中 innoDB 和myIsam 的區別
1、innodb和myisam是什么?
innodb和myisam是mysql最常用的兩種存儲引擎。
MySQL 有多種存儲引擎,每種存儲引擎有各自的優缺點(第3節說)。可以使用命令“show engines”查看引擎(下圖附命令以及顯示內容)。
2、innodb和myisam區別?
1)、事務和外鍵
InnoDB具有事務,支持4個事務隔離級別(讀未提交(Read Uncommitted),
讀已提交(Read Committed),可重復讀(Repeated Read),串行化(Serializable)),
回滾,崩潰修復能力和多版本並發的事務安全。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多用戶並發操作的性能。
MyISAM管理非事務表。它提供高速存儲和檢索,以及全文搜索能力。如果應用中需要執行大量的SELECT查詢,那么MyISAM是更好的選擇。
2)、鎖
mysql支持三種鎖定級別,行級、頁級、表級;
MyISAM支持表級鎖定,提供與 Oracle 類型一致的不加鎖讀取(non-locking read in SELECTs)
InnoDB支持行級鎖,InnoDB表的行鎖也不是絕對的,如果在執行一個SQL語句時MySQL不能確定要掃描的范圍,InnoDB表同樣會鎖全表,注意間隙鎖的影響。
例如update table set num=1 where name like “%aaa%”
3)、並發
MyISAM讀寫互相阻塞:不僅會在寫入的時候阻塞讀取,MyISAM還會在讀取的時候阻塞寫入,但讀本身並不會阻塞另外的讀。並發性能較差。
InnoDB 讀寫阻塞與事務隔離級別相關。
4)、索引
InnoDB(索引組織表)使用的聚簇索引、索引就是數據,順序存儲,因此能緩存索引,也能緩存數據。
MyISAM(堆組織表)使用的是非聚簇索引、索引和文件分開,隨機存儲,只能緩存索引。
5)、存儲
MyISAM在磁盤上存儲成三個文件。第一個文件的名字以表的名字開始,擴展名指出文件類型, .frm文件存儲表定義,數據文件的擴展名為.MYD, 索引文件的擴展名是.MYI。
InnoDB,基於磁盤的資源是InnoDB表空間數據文件和它的日志文件,InnoDB 表的大小只受限於操作系統文件的大小
注意:MyISAM表是保存成文件的形式,在跨平台的數據轉移中使用MyISAM存儲會省去不少的麻煩
2)、全文索引(基本沒人用,不需要關注,最好使用 ElasticSearch,Solr)
Innodb不支持全文索引,如果一定要用的話,最好使用sphinx等搜索引擎。myisam對中文支持的不是很好。
在 MySQL 5.7.6 之前,全文索引只支持英文全文索引,不支持中文全文索引,需要利用分詞器把中文段落預處理拆分成單詞,然后存入數據庫。
從 MySQL 5.7.6 開始,MySQL內置了ngram全文解析器,用來支持中文、日文、韓文分詞。
3、如何使用innodb和myisam?
mysql 5.5版本以及以后默認使用innoDB,如果創建表時候不指定存儲引擎默認使用 innoDB,如果不想使用默認的存儲引擎可以使用如下方法改變:
a、表創建默認存儲引擎:
create table table_name(
id int primary key,
name varchar(50)
) type=MyISAM;
b、表級修改存儲引擎:
alter table `Table_name` engine= MyISAM;
c、設置默認存儲引擎,配置文件my.ini :
my.ini,在[mysqld]最后添加為上default-storage-engine=myisam,重啟服務
如何避免sql注入漏洞
1、簡單又有效的方法使用PreparedStatement
采用預編譯語句集,它內置了處理SQL注入的能力,只要使用它的setXXX(如:setString)方法傳值即可。
使用好處:
(1).代碼的可讀性和可維護性變好
(2).PreparedStatement盡最大可能提高性能.
(3).最重要的一點是極大地提高了安全性.
原理:
sql注入只對sql語句的編譯過程有破壞作用,
而PreparedStatement sql語句編譯階段已經准備好了,執行階段只是把輸入串作為數據處理,
而不再對sql語句進行解析,准備,因此也就避免了sql注入問題。
我們的一些熱門ORM框架在處理sql時候也都使用了PreparedStatement
比如MyBatis,我們在使用MyBatis要注意:在注入參數值得時候使用#{xxxx}
#{xxxx} 已經啟用了預編譯功能,在SQL執行前,會先將上面的SQL發送給數據庫進行編譯;
執行時,直接使用編譯好的SQL,替換占位符“?”就可以了。因為SQL注入只能對編譯過程起作用,所以這樣的方式就很好地避免了SQL注入的問題。
“${xxx}”這樣格式的參數會直接參與SQL編譯,從而不能避免注入攻擊。有時有些操作要使用這種方式,比如傳入表,模糊匹配等。
可以使用bind + #{} 模糊查詢 防止SQL注入 (#{}進行預編譯,傳遞的參數不進行編譯,只作為參數,相當於PreparedStatement)
bind 元素可以從OGNL 表達式中創建一個變量並將其綁定到上下文。比如:
<select id="selectBlog" resultType="Blog">
<bind name="pattern" value="'%' + _parameter.getTitle() + '%'" />
SELECT * FROM BLOG
WHERE title LIKE #{pattern}
</select>
2.使用過濾器
如果我們做不到所有的sql語句都使用PreparedStatement,我們可以使用過濾器,進行全局的攔截這些字符串。在過濾器中,使用正則表達式過濾傳入的參數 。
正則表達式,判斷是否匹配:
String begin="您的請求參數信息 ";
String pattern="|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like";
//可以通過配置文件,去配置這些特殊字符,一邊隨時添加一些關鍵字
Pattern r = Pattern.compile(pattern);
Matcher isMatch = r.matcher( begin);
if(isMatch.find()){
//危險請求參數
}
參考:https://www.toutiao.com/i6792175892463354380/