文章目錄
- java 基礎
- HasMmap
- CurrentHashMap
- 行程與執行緒的區別
- 行程背景關系切換比執行緒背景關系切換
- 纖程
- 執行緒同步進制
- java執行緒同步機制
- 互斥鎖、自旋鎖、條件鎖、讀寫鎖、可重入鎖、偏向鎖、公平鎖、非公平鎖、可重入鎖、共享鎖、排它鎖、輕量級鎖、重量級鎖
- 死鎖產生的四個條件
- 有了互斥鎖,為什么還要條件鎖
- redis性能好的原因
- select、poll、epoll
- redis多并發競爭key
- 介面和抽象類
- hashcode equals ==
- ArrayList LinkedList
- TCP 三次握手 四次揮手
- 為什么連接的時候是三次握手,關閉的時候卻是四次握手
- 為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能回傳到CLOSE狀態
- 如果已經建立了連接,但是客戶端突然出現故障了怎么辦
- ThreadPoolExecutor的成員變數
- jvm-如何判斷物件需要回收
- jvm-垃圾回收演算法
- jvm-典型的垃圾收集器
- lock和synchronize的區別
- linux權限命令
- lock如何保證執行程序的可見性和有序性
- CAS 是怎么保證原子性的
- new出來的物件是一創建出來就進入堆中的嗎
- TLAB
- spring的aop實作的兩種方式
- spring的回圈依賴如何解決
- mysql日志種類
- MySQL中binlog和redo log的一致性問題
- Mysql-索引分類
- mysql-解決幻讀
- Spring-@Transaction生效
- 事務傳播行為
- Jvm記憶體溢位排查
- Mysql
- Mysql 怎么實作事務的
- Linux
- linux下查看行程下的執行緒資訊
java 基礎
HasMmap
- jdk1.7 頭插法擴容會出現死回圈
- jdk.1.8 尾插法put回出現資料覆寫丟失
CurrentHashMap
- jdk1.7 采用segment 分段鎖+hashEntry
- jdk1.8 采用synchronized+cas 實作,保留了segment只做序列化使用
采用ForwardingNodes,是的currentHashmap具有分段鎖特性
行程與執行緒的區別
(1)行程有自己的獨立地址空間,執行緒沒有
(2)行程是資源分配的最小單位,執行緒是CPU調度的最小單位
(3)行程和執行緒通信方式不同,同一行程下的執行緒共享資料(比如全域變數,靜態變數)
(4)行程背景關系切換開銷大,執行緒開銷小
(5)一個行程掛掉了不會影響其他行程,而執行緒掛掉了會影響其他執行緒
行程背景關系切換比執行緒背景關系切換
行程切換分兩步:
1.切換頁目錄以使用新的地址空間
2.切換內核堆疊和硬體背景關系
對于linux來說,執行緒和行程的最大區別就在于地址空間,對于執行緒切換,第1步是不需要做的,第2是行程和執行緒切換都要做的,
切換的性能消耗:
1、執行緒背景關系切換和行程上下問切換一個最主要的區別是執行緒的切換虛擬記憶體空間依然是相同的,但是行程切換是不同的,這兩種背景關系切換的處理都是通過作業系統內核來完成的,內核的這種切換程序伴隨的最顯著的性能損耗是將暫存器中的內容切換出,
2、另外一個隱藏的損耗是背景關系的切換會擾亂處理器的快取機制,簡單的說,一旦去切換背景關系,處理器中所有已經快取的記憶體地址一瞬間都作廢了,還有一個顯著的區別是當你改變虛擬記憶體空間的時候,處理的頁表緩沖(processor’s Translation Lookaside Buffer (TLB))被全部重繪,這將導致記憶體的訪問在一段時間內相當的低效,但是在執行緒的切換中,不會出現這個問題,
纖程
- 是用戶態的執行緒,是執行緒中的執行緒,切換和調度不需要經過作業系統
目前支持內置纖程的語言Kotlin Scala Go 等
執行緒同步進制
行程中執行緒同步的四種常用方式:
- 互斥量: 采用互斥物件機制,只有擁有互斥物件的執行緒才有訪問公共資源的權限,因為互斥物件只有一個,所以可以保證公共資源不會被多個執行緒同時訪問,
- 信號量: 它允許同一時刻多個執行緒來訪問同一資源,但是需要控制同一時刻訪問此資源的最大執行緒數量,
- 事件(信號):通過通知操作的方式來保持多執行緒同步,還可以方便實作多執行緒優先級的比較,
- 臨界區:臨界區物件和互斥物件非常相似,只是互斥量允許在行程間使用,而臨界區只限制與同一行程的各個執行緒之間使用,但是更節省資源,更有效率,
臨界區: 當多個執行緒訪問一個獨占性共享資源時,可以使用臨界區物件,擁有臨界區的執行緒可以訪問被保護起來的資源或代碼段,其他執行緒若想訪問,則被掛起,直到擁有臨界區的執行緒放棄臨界區為止,
java執行緒同步機制
- synchronized
- ReentrantLock
- Semaphore
- AtomicInteger
互斥鎖、自旋鎖、條件鎖、讀寫鎖、可重入鎖、偏向鎖、公平鎖、非公平鎖、可重入鎖、共享鎖、排它鎖、輕量級鎖、重量級鎖
- 互斥鎖
共享資源的使用是互斥的,即一個執行緒獲得資源的使用權后就會將該資源加鎖,使用完后會將其解鎖,如果在使用程序中有其他執行緒想要獲取該資源的鎖,那么它就會被阻塞陷入睡眠狀態,直到該資源被解鎖才會被喚醒,如果被阻塞的執行緒不止一個,那么它們都會被喚醒,但是獲得資源使用權的只有一個執行緒,其它執行緒又陷入沉睡.- 自旋鎖
自旋鎖是一種特殊的互斥鎖,當資源被枷鎖后,其他執行緒想要再次加鎖,此時該執行緒不會被阻塞睡眠而是陷入回圈等待狀態(不能在做其它事情),回圈檢查資源持有者是否已經釋放了資源,這樣做的好處是減少了執行緒從睡眠到喚醒的資源消耗,但會一直占用CPU的資源,適用于資源的鎖被持有的時間短,而又不希望在執行緒的喚醒上花費太多資源的情況,- 條件鎖
條件變數用來自動阻塞一個執行緒,直到某特殊情況發生,通常條件變數和互斥鎖同時使用,
條件變數使我們可以睡眠等待某條件出現,
條件變數是利用執行緒間共享的全域變數進行同步的一種機制,主要包括兩個動作:
1)一個執行緒因 “條件不成立” 而掛起等待
2)另一個執行緒使 “條件成立”, 并發出信號- 讀寫鎖
它擁有讀狀態加鎖、寫狀態加鎖、不加鎖這三種狀態,
只有一個執行緒可以占有寫狀態的鎖,但可以有多個執行緒同時占有讀狀態鎖,這也是它可以實作高并發的原因,當其處于寫狀態鎖下,任何想要嘗試獲得鎖的執行緒都會被阻塞,直到寫狀態鎖被釋放;如果是處于讀狀態鎖下,允許其它執行緒獲得它的讀狀態鎖,但是不允許獲得它的寫狀態鎖,直到所有執行緒的讀狀態鎖被釋放;為了避免想要嘗試寫操作的執行緒一直得不到寫狀態鎖,當讀寫鎖感知到有執行緒想要獲得寫狀態鎖時,便會阻塞其后所有想要獲得讀狀態鎖的執行緒,所以讀寫鎖非常適合資源的讀操作遠多于寫操作的情況- 可重入鎖
同一個執行緒可以多次獲得該資源鎖,別的執行緒必須等該執行緒釋放所有次數的鎖才可以獲得- 偏向鎖
大多數情況下,鎖不僅不存在多執行緒競爭,而且總是由同一個執行緒多次獲得,為了讓執行緒獲得鎖的代價更低而引入了偏向鎖,JDK1.6之后 偏向鎖默認開啟
偏向鎖是鎖狀態中最樂觀的一種鎖:從始至終只有一個執行緒請求同一把鎖
死鎖產生的四個條件
- 互斥條件:資源是獨占的且排他使用,行程互斥使用資源,即任意時刻一個資源只能給一個行程使用,其他行程若申請一個資源,而該資源被另一行程占有時,則申請者等待直到資源被占有者釋放,
- 不可剝奪條件:行程所獲得的資源在未使用完畢之前,不被其他行程強行剝奪,而只能由獲得該資源的行程資源釋放,
- 請求和保持條件:行程每次申請它所需要的一部分資源,在申請新的資源的同時,繼續占用已分配到的資源,
- 回圈等待條件:在發生死鎖時必然存在一個行程等待佇列{P1,P2,…,Pn},其中P1等待P2占有的資源,P2等待P3占有的資源,…,Pn等待P1占有的資源,形成一個行程等待環路,環路中每一個行程所占有的資源同時被另一個申請,也就是前一個行程占有后一個行程所深情地資源,
有了互斥鎖,為什么還要條件鎖
條件鎖反復嘗試上鎖,但無需進行內核切換
redis性能好的原因
- 放在記憶體里
- 單執行緒,省掉了執行緒切換的消耗
- 資料結構高效,對資料壓縮,跳表
- I/O多路復用 reactor模式
select、poll、epoll
redis多并發競爭key
zk 實作
zk 持久節點,持久節點順序節點,臨時節點,臨時順序節點
臨時順序節點 鏈表結構 parentLock -> node1->node2 node1執行完畢自動注銷掉
介面和抽象類
- 介面無構造方法,抽象類有構造方法
- 介面多實作,抽象類單繼承
- 抽象類中的成員變數可以是各種型別的,而介面中的成員變數只能是public static final型別的;
- 抽象類可以提供成員方法的實作細節,而介面中只能存在public abstract 方法;
- 介面中不能含有靜態代碼塊以及靜態方法,而抽象類可以有靜態代碼塊和靜態方法;
hashcode equals ==
- == 對于基本型別比較的值 對于參考型別比較的參考的地址
2.equals 比較的是值- hashcode
ArrayList LinkedList
- 如果應用程式對資料有較多的隨機訪問,ArrayList物件要優于LinkedList物件;
- 如果應用程式有更多的插入或者洗掉操作,較少的隨機訪問,LinkedList物件要優于ArrayList物件;
TCP 三次握手 四次揮手

三次握手
- 建立連接時,客戶端發送syn包(syn=j)到服務器,并進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)
- 服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態;
- 客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=k+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手,

四次揮手
- 客戶端行程發出連接釋放報文,并且停止發送資料,釋放資料報文首部,FIN=1,其序列號為seq=u(等于前面已經傳送過來的資料的最后一個位元組的序號加1),此時,客戶端進入FIN-WAIT-1(終止等待1)狀態,TCP規定,FIN報文段即使不攜帶資料,也要消耗一個序號,
- 服務器收到連接釋放報文,發出確認報文,ACK=1,ack=u+1,并且帶上自己的序列號seq=v,此時,服務端就進入了CLOSE-WAIT(關閉等待)狀態,TCP服務器通知高層的應用行程,客戶端向服務器的方向就釋放了,這時候處于半關閉狀態,即客戶端已經沒有資料要發送了,但是服務器若發送資料,客戶端依然要接受,這個狀態還要持續一段時間,也就是整個CLOSE-WAIT狀態持續的時間,
- 客戶端收到服務器的確認請求后,此時,客戶端就進入FIN-WAIT-2(終止等待2)狀態,等待服務器發送連接釋放報文(在這之前還需要接受服務器發送的最后的資料),
- 服務器將最后的資料發送完畢后,就向客戶端發送連接釋放報文,FIN=1,ack=u+1,由于在半關閉狀態,服務器很可能又發送了一些資料,假定此時的序列號為seq=w,此時,服務器就進入了LAST-ACK(最后確認)狀態,等待客戶端的確認,
- 客戶端收到服務器的連接釋放報文后,必須發出確認,ACK=1,ack=w+1,而自己的序列號是seq=u+1,此時,客戶端就進入了TIME-WAIT(時間等待)狀態,注意此時TCP連接還沒有釋放,必須經過2??MSL(最長報文段壽命)的時間后,當客戶端撤銷相應的TCB后,才進入CLOSED狀態,
- 服務器只要收到了客戶端發出的確認,立即進入CLOSED狀態,同樣,撤銷TCB后,就結束了這次的TCP連接,可以看到,服務器結束TCP連接的時間要比客戶端早一些,
為什么連接的時候是三次握手,關閉的時候卻是四次握手
因為當Server端收到Client端的SYN連接請求報文后,可以直接發送SYN+ACK報文,其中ACK報文是用來應答的,SYN報文是用來同步的,但是關閉連接時,當Server端收到FIN報文時,很可能并不會立即關閉SOCKET,所以只能先回復一個ACK報文,告訴Client端,“你發的FIN報文我收到了”,只有等到我Server端所有的報文都發送完了,我才能發送FIN報文,因此不能一起發送,故需要四步握手,
為什么TIME_WAIT狀態需要經過2MSL(最大報文段生存時間)才能回傳到CLOSE狀態
雖然按道理,四個報文都發送完畢,我們可以直接進入CLOSE狀態了,但是我們必須假象網路是不可靠的,有可以最后一個ACK丟失,所以TIME_WAIT狀態就是用來重發可能丟失的ACK報文,在Client發送出最后的ACK回復,但該ACK可能丟失,Server如果沒有收到ACK,將不斷重復發送FIN片段,所以Client不能立即關閉,它必須確認Server接收到了該ACK,Client會在發送出ACK之后進入到TIME_WAIT狀態,Client會設定一個計時器,等待2MSL的時間,如果在該時間內再次收到FIN,那么Client會重發ACK并再次等待2MSL,所謂的2MSL是兩倍的MSL(Maximum Segment Lifetime),MSL指一個片段在網路中最大的存活時間,2MSL就是一個發送和一個回復所需的最大時間,如果直到2MSL,Client都沒有再次收到FIN,那么Client推斷ACK已經被成功接收,則結束TCP連接,
如果已經建立了連接,但是客戶端突然出現故障了怎么辦
TCP還設有一個保活計時器,顯然,客戶端如果出現故障,服務器不能一直等下去,白白浪費資源,服務器每收到一次客戶端的請求后都會重新復位這個計時器,時間通常是設定為2小時,若兩小時還沒有收到客戶端的任何資料,服務器就會發送一個探測報文段,以后每隔75分鐘發送一次,若一連發送10個探測報文仍然沒反應,服務器就認為客戶端出了故障,接著就關閉連接,
ThreadPoolExecutor的成員變數
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler) {
if (corePoolSize < 0 ||
maximumPoolSize <= 0 ||
maximumPoolSize < corePoolSize ||
keepAliveTime < 0)
throw new IllegalArgumentException();
if (workQueue == null || threadFactory == null || handler == null)
throw new NullPointerException();
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.workQueue = workQueue;
this.keepAliveTime = unit.toNanos(keepAliveTime);
this.threadFactory = threadFactory;
this.handler = handler;
}
- corePoolSize核心池大小、maximumPoolSize最大執行緒數量,它們是用來控制執行緒的數目,總體流程為1:若小于Core則新建執行緒執行;2:若大于等于Core,則加入BlockingQueue;3:若BlockingQueue滿了之后,若小于Maximum,則新建執行緒來執行任務,若大于等于Maximum,則執行拒絕策略
- threadFactory執行緒工廠,它是用來創建執行緒的地方,Executors中默認的執行緒工廠會將守護執行緒屬性設定為false,執行緒的優先級設定為Normal登記;Executors還提供了權限執行緒工廠privilegedThreadFactory,可以對其的訪問權限進行控制
- BlockingQueue workQueue任務佇列,用來存放需要等待執行的任務,根據策略不同,Executors中提供了4種阻塞佇列,不含容量的同步佇列Synchronous佇列,它不保存任務,一直創建新的執行緒執行,直到到maximum,然后執行拒絕策略;LinkedBlockingQueue無界佇列,所以可以一直添加直到系統OOM;ArrayBlockingQueue它是有界的;PriorityBlockingQueue根據優先級的大小進行執行任務,Array和Linked則根據FIFO來執行任務
- keepAliveTime存活時間,對于超過CorePoolSize大小的執行緒最多存活的時間;
- rejectedExecutionHandler拒絕策略,對于超標,不能執行的拒絕策略;
jvm-如何判斷物件需要回收
- 參考計數法
缺點 回圈參考 造成記憶體泄露- 可達性分析
可作為root的
靜態屬性(被static修飾的屬性)
常量(被static final修飾的屬性)
虛擬機堆疊(本地變數表)中參考的物件
本地方法堆疊中參考的物件
jvm-垃圾回收演算法
- 標記-清除
- 標記-復制
- 標記-整理
- 分代回收
jvm-典型的垃圾收集器
1.Serial/Serial Old收集器 是最基本最古老的收集器,它是一個單執行緒收集器,并且在它進行垃圾收集時,必須暫停所有用戶執行緒,Serial收集器是針對新生代的收集器,采用的是Copying演算法,Serial Old收集器是針對老年代的收集器,采用的是Mark-Compact演算法,它的優點是實作簡單高效,但是缺點是會給用戶帶來停頓,
2.ParNew收集器 是Serial收集器的多執行緒版本,使用多個執行緒進行垃圾收集,
3.Parallel Scavenge收集器 是一個新生代的多執行緒收集器(并行收集器),它在回收期間不需要暫停其他用戶執行緒,其采用的是Copying演算法,該收集器與前兩個收集器有所不同,它主要是為了達到一個可控的吞吐量,
4.Parallel Old收集器 是Parallel Scavenge收集器的老年代版本(并行收集器),使用多執行緒和Mark-Compact演算法,
5.CMS(Concurrent Mark Sweep)收集器 是一種以獲取最短回收停頓時間為目標的收集器,它是一種并發收集器,采用的是Mark-Sweep演算法,
6.G1收集器 是當今收集器技術發展最前沿的成果,它是一款面向服務端應用的收集器,它能充分利用多CPU、多核環境,因此它是一款并行與并發收集器,并且它能建立可預測的停頓時間模型
lock和synchronize的區別

- Lock是一個介面,而synchronized是關鍵字,
- synchronized會自動釋放鎖,而Lock必須手動釋放鎖,
- Lock可以讓等待鎖的執行緒回應中斷,而synchronized不會,執行緒會一直等待下去,
- 通過Lock可以知道執行緒有沒有拿到鎖,而synchronized不能,
- Lock能提高多個執行緒讀操作的效率,
- synchronized能鎖住類、方法和代碼塊,而Lock是塊范圍內的
linux權限命令

lock如何保證執行程序的可見性和有序性
CAS 是怎么保證原子性的
- 當虛擬機遇到一條new指令時候,首先去檢查這個指令的引數是否能在常量池中能否定位到一個類的符號參考,并且檢查這個符號參考代表的類是否已被加載、決議和初始化過,如果沒有,那必須先執行相應的類加載程序,
- 在類加載檢查通過后,接下來虛擬機將為新生的物件分配記憶體,物件所需的記憶體的大小在類加載完成后便可以完全確定,為物件分配空間的任務等同于把一塊確定大小的記憶體從Java堆中劃分出來
2.1 指標碰撞(Bump the Pointer):假設Java堆的記憶體是絕對規整的,所有用過的記憶體都放一邊,空閑的記憶體放在另一邊,中間放著一個指標作為分界點的指示器,那所分配記憶體就僅僅把那個指標向空閑空間那邊挪動一段與物件大小相等的距離
2.2 空閑串列(Free List):如果Java堆中的記憶體并不是規整的,已使用的記憶體和空間的記憶體是相互交錯的,虛擬機必須維護一個空閑串列,記錄上哪些記憶體塊是可用的,在分配時候從串列中找到一塊足夠大的空間劃分給物件使用,- 在并發情況下劃分不一定是執行緒安全的,有可能出現正在給A物件分配記憶體,指標還沒有來得及修改,物件B又同時使用了原來的指標分配記憶體的情況,解決這個問題兩種方案:
3.1 分配記憶體空間的動作進行同步處理:實際上虛擬機采用CAS配上失敗重試的方式保證了更新操作的原子性
3.2 記憶體分配的動作按照執行緒劃分在不同的空間中進行:為每個執行緒在Java堆中預先分配一小塊記憶體,稱為本地執行緒分配緩沖(Thread Local Allocation Buffer, TLAB)- 記憶體分配完成后,進行初始化
new出來的物件是一創建出來就進入堆中的嗎
逃逸分析(Escape Analysis) - 分析物件的動態作用域,假如我們在一個方法內定義了一個物件,如果它被作為引數傳遞到其他地方,被本方法外的方法參考,這就就叫做方法逃逸
如果我們經過逃逸分析發現,某個物件并沒有發生方法逃逸,那么它的生命周期則始于方法呼叫,卒于方法結束,那么此時它就是方法內的區域變數,而堆記憶體是執行緒間共享的,如果將它分配到堆中,方法結束后,它將不在被任何物件所參考,還需要GC進行回收,很不劃算,于是 JIT就會將其分配到方法的堆疊幀中,這就是堆疊上分配,實際上在HotSpot中,堆疊上分配并不是直接在方法的堆疊幀中放入一個物件,它是通過標量替換的方式存盤的,即將物件分解成組成物件的若干個成員變數,這些變數是無法再分解的更小的資料,叫做標量,然后用這些標量來代替之前的物件,這就叫標量替換,通過標量替換,原本的一個物件,被替換成多個成員變數,而原本需要在堆上分配的記憶體,也就不再需要了,完全可以在本地方法堆疊中完成對成員變數的記憶體分配,
TLAB
TLAB (Thread Local Allocation Buffer,執行緒本地分配緩沖區)是 Java 中記憶體分配的一個概念,它是在 Java 堆中劃分出來的針對每個執行緒的記憶體區域,專門在該區域為該執行緒創建的物件分配記憶體,它的主要目的是在多執行緒并發環境下需要進行記憶體分配的時候,減少執行緒之間對于記憶體分配區域的競爭,加速記憶體分配的速度,TLAB 本質上還是在 Java 堆中的,因此在 TLAB 區域的物件,也可以被其他執行緒訪問
如果沒有啟用 TLAB,多個并發執行的執行緒需要創建物件、申請分配記憶體的時候,有可能在 Java 堆的同一個位置申請,這時就需要對擬分配的記憶體區域進行加鎖或者采用 CAS 等操作,保證這個區域只能分配給一個執行緒
啟用了 TLAB 之后(-XX:+UseTLAB, 默認是開啟的),JVM 會針對每一個執行緒在 Java 堆中預留一個記憶體區域,在預留這個動作發生的時候,需要進行加鎖或者采用 CAS 等操作進行保護,避免多個執行緒預留同一個區域,一旦某個區域確定劃分給某個執行緒,之后該執行緒需要分配記憶體的時候,會優先在這片區域中申請,這個區域針對分配記憶體這個動作而言是該執行緒私有的,因此在分配的時候不用進行加鎖等保護性的操作
spring的aop實作的兩種方式
- 一種是采用宣告的方式來實作(基于XML)
- 一種是采用注解的方式來實作(基于AspectJ)
spring的回圈依賴如何解決
- Spring實體化一個bean的時候,是分兩步進行的,首先實體化目標bean,然后為其注入屬性,
- Spring是通過遞回的方式獲取目標bean及其所依賴的bean的;
- Spring解決回圈依賴問題是通過結合bean實體化和bean屬性填裝分離,singletonObjects、earlySingletonObjects 、singletonFactories 三級快取機制和參考提前暴露機制實作的
mysql日志種類
重做日志(redo log
確保事務的持久性,防止在發生故障的時間點,尚有臟頁未寫入磁盤,在重啟mysql服務的時候,根據redo log進行重做,從而達到事務的持久性這一特性,
內容:
物理格式的日志,記錄的是物理資料頁面的修改的資訊,其redo log是順序寫入redo log file的物理檔案中去的,回滾日志(undo log)
保存了事務發生之前的資料的一個版本,可以用于回滾,同時可以提供多版本并發控制下的讀(MVCC),也即非鎖定讀
邏輯格式的日志,在執行undo的時候,僅僅是將資料從邏輯上恢復至事務之前的狀態,而不是從物理頁面上操作實作的,這一點是不同于redo log的,二進制日志(binlog)
3.1 用于復制,在主從復制中,從庫利用主庫上的binlog進行重播,實作主從同步,
3.2 用于資料庫的基于時間點的還原
邏輯格式的日志,可以簡單認為就是執行過的事務中的sql陳述句,錯誤日志(errorlog)
慢查詢日志(slow query log)
一般查詢日志(general log)
中繼日志(relay log)
MySQL中binlog和redo log的一致性問題
Mysql-索引分類
- FULLTEXT即為全文索引,目前只有MyISAM引擎支持,其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不過目前只有 CHAR、VARCHAR ,TEXT 列上可以創建全文索引,
全文索引并不是和MyISAM一起誕生的,它的出現是為了解決WHERE name LIKE “%word%"這類針對文本的模糊查詢效率較低的問題,- HASH
由于HASH的唯一及類似鍵值對的形式,很適合作為索引,
HASH索引可以一次定位,不需要像樹形索引那樣逐層查找,因此具有極高的效率,但是,這種高效是有條件的,即只在“=”和“in”條件下高效,對于范圍查詢、排序及組合索引仍然效率不高,- BTREE
BTREE索引就是一種將索引值按一定的演算法,存入一個樹形的資料結構中(二叉樹),每次查詢都是從樹的入口root開始,依次遍歷node,獲取leaf,這是MySQL里默認和最常用的索引型別,- RTREE
RTREE在MySQL很少使用,僅支持geometry資料型別,支持該型別的存盤引擎只有MyISAM、BDb、InnoDb、NDb、Archive幾種,
mysql-解決幻讀
- 如果是快照讀mvcc
InnoDB為每行記錄添加了一個版本號(系統版本號),每當修改資料時,版本號加一,
在讀取事務開始時,系統會給事務一個當前版本號,事務會讀取版本號<=當前版本號的資料,這時就算另一個事務插入一個資料,并立馬提交,新插入這條資料的版本號會比讀取事務的版本號高,因此讀取事務讀的資料還是不會變,- 如果是當前讀 next-key lock
如果是當前讀,那么是通過Gap Lock鎖來避免幻讀
Spring-@Transaction生效
- @Transactional 注解只能應用到 public 可見度的方法上,
- 在類內部呼叫將不起作用,
- 只有在外部呼叫的情況下才能引起事務,是由于Spring Aop的本質決定的
事務傳播行為
- TransactionDefinition.PROPAGATION_REQUIRED:如果當前存在事務,則加入該事務;如果當前沒有事務,則創建一個新的事務,
- TransactionDefinition.PROPAGATION_REQUIRES_NEW:創建一個新的事務,如果當前存在事務,則把當前事務掛起,
- TransactionDefinition.PROPAGATION_SUPPORTS:如果當前存在事務,則加入該事務;如果當前沒有事務,則以非事務的方式繼續運行,
- TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事務方式運行,如果當前存在事務,則把當前事務掛起,
- TransactionDefinition.PROPAGATION_NEVER:以非事務方式運行,如果當前存在事務,則拋出例外,
- TransactionDefinition.PROPAGATION_MANDATORY:如果當前存在事務,則加入該事務;如果當前沒有事務,則拋出例外,
- TransactionDefinition.PROPAGATION_NESTED:如果當前存在事務,則創建一個事務作為當前事務的嵌套事務來運行;如果當前沒有事務,則該取值等價TransactionDefinition.PROPAGATION_REQUIRED
Jvm記憶體溢位排查
- jmap -heap pid
- 下載MemoryAnalyzer MAT工具匯入第一步匯出的heap.bin進行分析
Mysql
Mysql 怎么實作事務的
Linux
linux下查看行程下的執行緒資訊
- ps -mp pid -o THREAD,tid,time
- printf “%x\n” tid 把十進制的tid轉16進制的id
- jstack pid |grep tid -A 1000
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/303307.html
標籤:java
上一篇:剛開始學資料結構不太明白?8000字吐血總結資料結構之單鏈表
下一篇:Redis為什么這么快?
