表單input:表單是用來收集信息的,由表單控件(表單元素)、提示信息、表單域構成。
input控件的屬性及值:
除以上屬性外,input元素type屬性還有一個number屬性值,此為僅可以填數字,默認是可以選擇或者填寫任意數字,但是當type屬性為number屬性值時,可以使用max和min屬性來限制數字的取值范圍,input更多屬性見HTML5
<input type="number" min="0"> <!-- min屬性限定最小值為0 -->
label標簽:
label標簽是為input標簽服務的,用于綁定一個表單元素, 當點擊label標簽的時候, 被綁定的表單元素就會獲得輸入焦點
<label> <!-- 1、直接使用label標簽包裹要點擊的元素獲得焦點 -->
姓名:<input type="text">
</label>
<label for="name">姓名:</label> <!-- 2、使用label標簽的for屬性找input元素獲得焦點 -->
<input id="name" type="text"/>
表單域form:
form元素用于創建一個表單,form中的所有內容都會被提交給服務器;默認form標簽中需要有一個submit按鈕,如果form里面沒有submit按鈕,那么可以使用button中type屬性為submit的button按鈕,這個buttont按鈕可能不在form表單中,此時可以給type屬性值為submit的button添加form屬性,值為form表單的id值,如:
<form action="" method="get" name="" id="userform"> <!-- action屬性是指定表單提交給后端的地址,method屬性設置提交方式,其屬性值有post和get,name屬性用來給表單域定義名字,用于區分表單域 -->
姓名:<input type="text">
年齡:<input type="number" min="0">
</form>
<button type="submit" form="userform">提交</button>
文本域textarea:
input元素只能顯示一行內容,textarea元素可以顯示多行,一般做留言效果使用,常常被稱為富文本域。
<!-- rows屬性限定行數,當行數超過限定后會出現滾動條,cols屬性限定的是列數,當超過限定后會換行。 -->
<textarea cols="20" rows="10"></textarea>
UEditor:在實際開發中如果需要用到比較復雜的富文本域(類似word的,可以上傳視頻圖片等功能)推薦使用第三方插件,這里推薦大家一款使用的富文本插件:UEditor,使用它可以在網頁中實現類似word等編輯,如果想要了解更多及方法請查閱官方文檔:http://fex.baidu.com/ueditor/,當然類似的富文本編輯器還有很多,如:CKeditor:https://ckeditor.com/等
富文本編輯器可以自己做,其原理是利用document的execCommand()方法,這個方法實際開發中很少用,已經廢棄,所以一般很少有人了解,如果想要了解更多,可閱讀官方文檔:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/execCommand
下拉列表(下拉菜單)select:
<body>
<select name="" id="">
<optgroup value="" label="分組1"><!-- optgroup標簽用來分組 -->>
<option value="">
測試1
</option>
<option value="">
測試2
</option>
<option value="">
測試3
</option>
</optgroup>
<optgroup value="" label="分組2">
<option value="">選項1</option> <!-- select默認選擇第一個option,當給option加selected屬性時,則會選中此項顯示 -->
<option value="" selected="selected">選項2</option> <!-- selected屬性的selected屬性值可以省略,其效果不變-->
<option value="">選項3</option>
</optgroup>
</select>
</body>
塊引用標簽:
有的時候會引用名人名言等,此時建議使用引用標簽,引用標簽分為長引用和短引用兩種,長引用標簽效果是插入換行和外邊距,短引用標簽的效果是加上虛擬的引號。
<blockquote>海上生明月,天涯共此時。</blockquote><!-- 長引用標簽 -->
<q>引號</q><!-- 段引用會給內容加上虛擬的引號,這個引號根本不存在。 -->
提示:本文圖片等素材來源于網絡,若有侵權,請發郵件至郵箱:810665436@qq.com聯系筆者 刪除。
筆者:苦海123
其它問題可通過以下方式聯系本人咨詢:
QQ:810665436
微信:ConstancyMan
JavaScript
大家在面試中有沒遇到面試官問你下面六句Sql的區別呢
select * from table where id = ? select * from table where id < ? select * from table where id = ? lock in share mode select * from table where id < ? lock in share mode select * from table where id = ? for update select * from table where id < ? for update 復制代碼
如果你能清楚的說出,這六句sql在不同的事務隔離級別下,是否加鎖,加的是共享鎖還是排他鎖,是否存在間隙鎖,那這篇文章就沒有看的意義了。 之所以寫這篇文章是因為目前為止網上這方面的文章太片面,都只說了一半,且大多沒指明隔離級別,以及where后跟的是否為索引條件列。在此,我就不一一列舉那些有誤的文章了,大家可以自行百度一下,大多都是講不清楚。 OK,要回答這個問題,先問自己三個問題
OK,開始回答
正文
下面啰嗦點基礎知識
鎖類型
共享鎖(S鎖):假設事務T1對數據A加上共享鎖,那么事務T2可以讀數據A,不能修改數據A。
排他鎖(X鎖):假設事務T1對數據A加上共享鎖,那么事務T2不能讀數據A,不能修改數據A。 我們通過update、delete等語句加上的鎖都是行級別的鎖。只有LOCK TABLE … READ和LOCK TABLE … WRITE才能申請表級別的鎖。
意向共享鎖(IS鎖):一個事務在獲取(任何一行/或者全表)S鎖之前,一定會先在所在的表上加IS鎖。
意向排他鎖(IX鎖):一個事務在獲取(任何一行/或者全表)X鎖之前,一定會先在所在的表上加IX鎖。
意向鎖存在的目的?
OK,這里說一下意向鎖存在的目的。假設事務T1,用X鎖來鎖住了表上的幾條記錄,那么此時表上存在IX鎖,即意向排他鎖。那么此時事務T2要進行LOCK TABLE … WRITE的表級別鎖的請求,可以直接根據意向鎖是否存在而判斷是否有鎖沖突。
加鎖算法
我的說法是來自官方文檔: https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html 加上自己矯揉造作的見解得出。
ok,記得如下三種,本文就夠用了
Record Locks:簡單翻譯為行鎖吧。注意了,該鎖是對索引記錄進行加鎖!鎖是在加索引上而不是行上的。注意了,innodb一定存在聚簇索引,因此行鎖最終都會落到聚簇索引上!
Gap Locks:簡單翻譯為間隙鎖,是對索引的間隙加鎖,其目的只有一個,防止其他事物插入數據。在Read Committed隔離級別下,不會使用間隙鎖。這里我對官網補充一下,隔離級別比Read Committed低的情況下,也不會使用間隙鎖,如隔離級別為Read Uncommited時,也不存在間隙鎖。當隔離級別為Repeatable Read和Serializable時,就會存在間隙鎖。
Next-Key Locks:這個理解為Record Lock+索引前面的Gap Lock。記住了,鎖住的是索引前面的間隙!比如一個索引包含值,10,11,13和20。那么,間隙鎖的范圍如下
(negative infinity, 10] (10, 11] (11, 13] (13, 20] (20, positive infinity) 復制代碼
快照讀和當前讀
最后一點基礎知識了,大家堅持看完,這些是后面分析的基礎! 在mysql中select分為快照讀和當前讀,執行下面的語句
select * from table where id = ?; 復制代碼
執行的是快照讀,讀的是數據庫記錄的快照版本,是不加鎖的。(這種說法在隔離級別為Serializable中不成立,后面我會補充。) 那么,執行
select * from table where id = ? lock in share mode; 復制代碼
會對讀取記錄加S鎖 (共享鎖),執行
select * from table where id = ? for update 復制代碼
會對讀取記錄加X鎖 (排他鎖),那么
加的是表鎖還是行鎖呢?
針對這點,我們先回憶一下事務的四個隔離級別,他們由弱到強如下所示:
那么關于是表鎖還是行鎖,大家可以看到網上最流傳的一個說法是這樣的,
InnoDB行鎖是通過給索引上的索引項加鎖來實現的,這一點MySQL與Oracle不同,后者是通過在數據塊中對相應數據行加鎖來實現的。 InnoDB這種行鎖實現特點意味著:只有通過索引條件檢索數據,InnoDB才使用行級鎖,否則,InnoDB將使用表鎖!
這句話大家可以搜一下,都是你抄我的,我抄你的。那么,這句話本身有兩處錯誤! 錯誤一:并不是用表鎖來實現鎖表的操作,而是利用了Next-Key Locks,也可以理解為是用了行鎖+間隙鎖來實現鎖表的操作! 為了便于說明,我來個例子,假設有表數據如下,pId為主鍵索引
pId(int) name(varchar) num(int) 1 aaa 100 2 bbb 200 7 ccc 200 執行語句(name列無索引)
select * from table where name = `aaa` for update 復制代碼
那么此時在pId=1,2,7這三條記錄上存在行鎖(把行鎖住了)。另外,在(-∞,1)(1,2)(2,7)(7,+∞)上存在間隙鎖(把間隙鎖住了)。因此,給人一種整個表鎖住的錯覺!
ps:對該結論有疑問的,可自行執行show engine innodb status;語句進行分析。
錯誤二:所有文章都不提隔離級別!
注意我上面說的,之所以能夠鎖表,是通過行鎖+間隙鎖來實現的。那么,RU和RC都不存在間隙鎖,這種說法在RU和RC中還能成立么? 因此,該說法只在RR和Serializable中是成立的。如果隔離級別為RU和RC,無論條件列上是否有索引,都不會鎖表,只鎖行!
分析
下面來對開始的問題作出解答,假設有表如下,pId為主鍵索引
pId(int) name(varchar) num(int) 1 aaa 100 2 bbb 200 3 bbb 300 7 ccc 200 RC/RU+條件列非索引
(1)select * from table where num = 200
不加任何鎖,是快照讀。
(2)select * from table where num > 200
不加任何鎖,是快照讀。
(3)select * from table where num = 200 lock in share mode
當num = 200,有兩條記錄。這兩條記錄對應的pId=2,7,因此在pId=2,7的聚簇索引上加行級S鎖,采用當前讀。
(4)select * from table where num > 200 lock in share mode
當num > 200,有一條記錄。這條記錄對應的pId=3,因此在pId=3的聚簇索引上加上行級S鎖,采用當前讀。
(5)select * from table where num = 200 for update
當num = 200,有兩條記錄。這兩條記錄對應的pId=2,7,因此在pId=2,7的聚簇索引上加行級X鎖,采用當前讀。
(6)select * from table where num > 200 for update
當num > 200,有一條記錄。這條記錄對應的pId=3,因此在pId=3的聚簇索引上加上行級X鎖,采用當前讀。
RC/RU+條件列是聚簇索引
恩,大家應該知道pId是主鍵列,因此pId用的就是聚簇索引。此情況其實和RC/RU+條件列非索引情況是類似的。
(1)select * from table where pId = 2
不加任何鎖,是快照讀。
(2)select * from table where pId > 2
不加任何鎖,是快照讀。
(3)select * from table where pId = 2 lock in share mode
在pId=2的聚簇索引上,加S鎖,為當前讀。
(4)select * from table where pId > 2 lock in share mode
在pId=3,7的聚簇索引上,加S鎖,為當前讀。
(5)select * from table where pId = 2 for update
在pId=2的聚簇索引上,加X鎖,為當前讀。
(6)select * from table where pId > 2 for update
在pId=3,7的聚簇索引上,加X鎖,為當前讀。
這里,大家可能有疑問
為什么條件列加不加索引,加鎖情況是一樣的?
ok,其實是不一樣的。在RC/RU隔離級別中,MySQL Server做了優化。在條件列沒有索引的情況下,盡管通過聚簇索引來掃描全表,進行全表加鎖。但是,MySQL Server層會進行過濾并把不符合條件的鎖當即釋放掉,因此你看起來最終結果是一樣的。但是RC/RU+條件列非索引比本例多了一個釋放不符合條件的鎖的過程!
RC/RU+條件列是非聚簇索引
我們在num列上建上非唯一索引。此時有一棵聚簇索引(主鍵索引,pId)形成的B+索引樹,其葉子節點為硬盤上的真實數據。以及另一棵非聚簇索引(非唯一索引,num)形成的B+索引樹,其葉子節點依然為索引節點,保存了num列的字段值,和對應的聚簇索引。
接下來分析開始
(1)select * from table where num = 200
不加任何鎖,是快照讀。
(2)select * from table where num > 200
不加任何鎖,是快照讀。
(3)select * from table where num = 200 lock in share mode
當num = 200,由于num列上有索引,因此先在 num = 200的兩條索引記錄上加行級S鎖。接著,去聚簇索引樹上查詢,這兩條記錄對應的pId=2,7,因此在pId=2,7的聚簇索引上加行級S鎖,采用當前讀。
(4)select * from table where num > 200 lock in share mode
當num > 200,由于num列上有索引,因此先在符合條件的 num = 300的一條索引記錄上加行級S鎖。接著,去聚簇索引樹上查詢,這條記錄對應的pId=3,因此在pId=3的聚簇索引上加行級S鎖,采用當前讀。
(5)select * from table where num = 200 for update
當num = 200,由于num列上有索引,因此先在 num = 200的兩條索引記錄上加行級X鎖。接著,去聚簇索引樹上查詢,這兩條記錄對應的pId=2,7,因此在pId=2,7的聚簇索引上加行級X鎖,采用當前讀。
(6)select * from table where num > 200 for update
當num > 200,由于num列上有索引,因此先在符合條件的 num = 300的一條索引記錄上加行級X鎖。接著,去聚簇索引樹上查詢,這條記錄對應的pId=3,因此在pId=3的聚簇索引上加行級X鎖,采用當前讀。
RR/Serializable+條件列非索引
RR級別需要多考慮的就是gap lock,他的加鎖特征在于,無論你怎么查都是鎖全表。如下所示 接下來分析開始
(1)select * from table where num = 200
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加S鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
(2)select * from table where num > 200
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加S鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
(3)select * from table where num = 200 lock in share mode
在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加S鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
(4)select * from table where num > 200 lock in share mode
在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加S鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
(5)select * from table where num = 200 for update
在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加X鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
(6)select * from table where num > 200 for update
在pId = 1,2,3,7(全表所有記錄)的聚簇索引上加X鎖。并且在 聚簇索引的所有間隙(-∞,1)(1,2)(2,3)(3,7)(7,+∞)加gap lock
RR/Serializable+條件列是聚簇索引
恩,大家應該知道pId是主鍵列,因此pId用的就是聚簇索引。該情況的加鎖特征在于,如果where后的條件為精確查詢(=的情況),那么只存在record lock。如果where后的條件為范圍查詢(>或<的情況),那么存在的是record lock+gap lock。
(1)select * from table where pId = 2
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,是當前讀,在pId=2的聚簇索引上加S鎖,不存在gap lock。
(2)select * from table where pId > 2
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,是當前讀,在pId=3,7的聚簇索引上加S鎖。在(2,3)(3,7)(7,+∞)加上gap lock
(3)select * from table where pId = 2 lock in share mode
是當前讀,在pId=2的聚簇索引上加S鎖,不存在gap lock。
(4)select * from table where pId > 2 lock in share mode
是當前讀,在pId=3,7的聚簇索引上加S鎖。在(2,3)(3,7)(7,+∞)加上gap lock
(5)select * from table where pId = 2 for update
是當前讀,在pId=2的聚簇索引上加X鎖。
(6)select * from table where pId > 2 for update
在pId=3,7的聚簇索引上加X鎖。在(2,3)(3,7)(7,+∞)加上gap lock
(7)select * from table where pId = 6 [lock in share mode|for update]
注意了,pId=6是不存在的列,這種情況會在(3,7)上加gap lock。
(8)select * from table where pId > 18 [lock in share mode|for update]
注意了,pId>18,查詢結果是空的。在這種情況下,是在(7,+∞)上加gap lock。
RR/Serializable+條件列是非聚簇索引
這里非聚簇索引,需要區分是否為唯一索引。因為如果是非唯一索引,間隙鎖的加鎖方式是有區別的。
先說一下,唯一索引的情況。如果是唯一索引,情況和RR/Serializable+條件列是聚簇索引類似,唯一有區別的是:這個時候有兩棵索引樹,加鎖是加在對應的非聚簇索引樹和聚簇索引樹上!大家可以自行推敲!
下面說一下,非聚簇索引是非唯一索引的情況,他和唯一索引的區別就是通過索引進行精確查詢以后,不僅存在record lock,還存在gap lock。而通過唯一索引進行精確查詢后,只存在record lock,不存在gap lock。老規矩在num列建立非唯一索引
(1)select * from table where num = 200
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,是當前讀,在pId=2,7的聚簇索引上加S鎖,在num=200的非聚集索引上加S鎖,在(100,200)(200,300)加上gap lock。
(2)select * from table where num > 200
在RR級別下,不加任何鎖,是快照讀。 在Serializable級別下,是當前讀,在pId=3的聚簇索引上加S鎖,在num=300的非聚集索引上加S鎖。在(200,300)(300,+∞)加上gap lock
(3)select * from table where num = 200 lock in share mode
是當前讀,在pId=2,7的聚簇索引上加S鎖,在num=200的非聚集索引上加S鎖,在(100,200)(200,300)加上gap lock。
(4)select * from table where num > 200 lock in share mode
是當前讀,在pId=3的聚簇索引上加S鎖,在num=300的非聚集索引上加S鎖。在(200,300)(300,+∞)加上gap lock。
(5)select * from table where num = 200 for update
是當前讀,在pId=2,7的聚簇索引上加S鎖,在num=200的非聚集索引上加X鎖,在(100,200)(200,300)加上gap lock。
(6)select * from table where num > 200 for update
是當前讀,在pId=3的聚簇索引上加S鎖,在num=300的非聚集索引上加X鎖。在(200,300)(300,+∞)加上gap lock
(7)select * from table where num = 250 [lock in share mode|for update]
注意了,num=250是不存在的列,這種情況會在(200,300)上加gap lock。
(8)select * from table where num > 400 [lock in share mode|for update]
注意了,pId>400,查詢結果是空的。在這種情況下,是在(400,+∞)上加gap lock。
原文地址:rjzheng.cnblogs.com/
歡迎關注頭條號:JAVA大飛哥
點擊關注評論轉發一波:私信小編發送“架構”(免費獲取)
獲取微服務、分布式、高并發、高可用,性能優化丶Mysql源碼分析等等一些技術資料
最后,每一位讀到這里的Java程序猿朋友們,感謝你們能耐心地看完。希望在成為一名更優秀的Java程序猿的道路上,我們可以一起學習、一起進步!都能贏取白富美,走向架構師的人生巔峰!
*請認真填寫需求信息,我們會在24小時內與您取得聯系。