1. 程式人生 > 其它 >Oracle拆分字串函式

Oracle拆分字串函式

1、鎖分類
-悲觀鎖-Pessimistic lock
全域性鎖:flush table with read lock;使用全域性鎖會鎖住整個資料庫,使其處於只讀狀態;
表鎖: lock table和 意向鎖(Intention Locks) MataData Lock ,意向鎖不用顯示呼叫;
行鎖(Record-lock)
間隙鎖( gap locks)
臨鍵鎖( next-key lock) ,由行鎖和間隙鎖組成;
-樂觀鎖- Optimistic Lock
自旋cas機制;可通過version版本和時間戳來判斷;


2、全域性鎖
2.1 全域性鎖: flush tables with lock:全域性鎖主要是對整個資料庫的例項加鎖,一個庫被全域性鎖鎖住後處於只讀狀態,以下動作將會被禁止:
DML:data manipulation language 對資料的增查改刪更新操作;
DDL: data definition language ,包括對錶的修改,增加欄位刪除欄位;
使用場景:全庫邏輯備份。如果沒有全域性鎖,那麼系統備份得到的資料不是一個邏輯時間點的,這個檢視的邏輯是不一致的,資料備份會出現問題。

3、表鎖


3.1 lock tables 表鎖
加鎖:lock table tableName read/write;
解鎖:unlock table:
使用場景 :在沒有行鎖這種粒度鎖的時候,處理併發的時候就會使用表級鎖;
lock table car write;
select * from car;
unlock tables;
特點:

(1). 可以主動unlock tables釋放,在客戶端斷開連線的時候自動釋放;
(2). lock tables除了限制別的執行緒的讀寫外,也限定了本執行緒接下來的操作物件;
例如執行緒執行:
lock tables t1 read, t2 write; //除了阻塞其他執行緒外,自己本身也只能讀t1,讀寫t2,不能寫t1.
3.2 MDL-意向鎖
Mate Data Lock, 意向鎖 -也稱為 元資料鎖 ,在mysql5.5版本中引入了MDL,引擎自己維護,使用者不用手動操作。當對一個表做增查改刪的時候+MDL讀鎖,當要對錶結果做變更的時候,+MDL寫鎖。
意向共享鎖:如果一張表上面至少有一個意向共享鎖,說明有其他的事務給其中的某些資料行加上了共享鎖;
意向排他鎖:如果一張表上面至少有一個意向排他鎖,說明有其他的事務給其中的某些資料行加上了排他鎖;
作用:
(1)是防止DDL和MDL之間衝突,保證DDL-(資料定義語言)和DML-(操縱語言:增查改刪)的資料一致性;
MDL的(增查改刪)讀鎖和 DDL之間不互斥;
MDL的寫鎖和DDL的寫鎖修改表結構之間互斥;在對錶結構進行修改時,加MDL鎖,另外執行緒只能等待。
(2)提高加鎖的效率;
加x鎖的前提是:表中沒有任何鎖,包括行鎖的存在,意向鎖避免了加行鎖時檢查鎖狀態的全錶行鎖掃描,先加意向鎖後加x鎖,它相當於一個標記,提高了加鎖的效率;


4、行鎖【Innodb】
4.1、行鎖實現原理
行鎖是儲存引擎innodb自己設計的,不是所有的儲存引擎都支援,比如myisam就不支援;
行鎖是基於索引實現的,所以沒有建立索引的更新將會掃描全表,使用的是表鎖;通過鎖住索引實現行及鎖。
如果select …for update沒走索引,就會鎖表,innodb內部是全表根據主鍵索引逐行掃描,逐行加鎖,最後統一釋放。

使用注意點: 沒有索引或者索引失效時,InnoDB 的行鎖變表鎖。
4.2、兩階段鎖協議
行鎖是需要的時候加上的,不是不需要了就立即釋放,在commit後才釋放,釋放時機如下:
1. 執行commit語句或者rollback;
2. 退出資料庫;
3. 客戶端斷開連線;
4.3、行鎖的使用優化
由於行鎖的等到事務提交後才釋放,不是用完就釋放,所以把有衝突的搶鎖操作儘量放到事務操作的最後一步進行。如何理解: “儘量把臨界資源的鎖往後放”,例項如下:
例項場景:支付訂單中一般流程較長,步驟較多,比如商品庫存就是一臨界資源,容易產生競爭,可以將扣減庫存放在訂單事務操作的最後一步,讓事務在獲取鎖的等待時間儘量短,提高併發度。


5、行鎖與索引的關係分析
從一條簡單的SQL語句開始,分析索引對加鎖的影響:
SQL: delete from Order where orderId = 33;
情況一:在RC級別下,id為主鍵索引,orderId為普通索引,忽略訂單ID重複的情況;

表結構如下:
CREATE TABLE `Order` (
`id` int(11) NOT NULL,
`orderId` bigint NOT NULL,
`goods_name` varchar(45) DEFAULT NULL COMMENT '商品名稱',
PRIMARY KEY (`id`),
KEY `orderId` (`orderId`)
) ENGINE=InnoDB


分析:此時加行鎖會鎖住對應條件的二級索引及主鍵索引的行記錄;
情況二:在RC級別下,id為主鍵索引,orderId為唯一索引;
表結構如下:
CREATE TABLE `Order` (
`id` int(11) NOT NULL,
`orderId` bigint NOT NULL,
`goods_name` varchar(45) DEFAULT NULL COMMENT '商品名稱',
PRIMARY KEY (`id`),
UNIQUE KEY `orderId_UNIQUE` (`orderId`),
) ENGINE=InnoDB


分析:由於id是唯一索引時,where會走orderIde列的索引進行過濾,在找到orderId=33的記錄後對唯一索引orderId=33的記錄加X鎖。
同時會回表查詢主鍵索引orderId=33的資料,並對orderId=33的資料也加上X鎖。此時依然加行鎖,鎖住唯一索引及主鍵索引對應的行記錄

情況三:在RC級別下,只有id主鍵索引;
表結構如下:
CREATE TABLE `Order` (
`id` int(11) NOT NULL,
`orderId` bigint NOT NULL,
`goods_name` varchar(45) DEFAULT NULL COMMENT '商品名稱',
PRIMARY KEY (`id`),
) ENGINE=InnoDB


分析:從上面分析的行鎖的鎖原理可知,因為沒有索引,所以走的是全表掃描,此時沒有行鎖,會對主鍵索引上每一條記錄施加X鎖,會鎖住整個的表資料;
思考: 為什麼會對所有記錄施加X鎖,而不是表鎖或者說符合條件的資料加X鎖呢?
這是由於InnoDB的實現決定的,由於沒有索引, 無法在儲存引擎層過濾(執行計劃裡的Using Where),所以儲存引擎對每一條資料加鎖後返回給Sql Server進行過濾,因為Innodb的行鎖是通過索引來實現的。
5.1、行鎖使用的注意事項
(1)在不通過索引條件查詢的時候,或沒有索引的情況下,InnoDB只能使用表鎖。
(2)由於MySQL的行鎖是針對索引加的鎖,不是針對記錄加的鎖,所以雖然是訪問不同行的記錄,但是如果是使用相同的索引鍵,是會出現鎖衝突的。
(3)當表有多個索引的時候,不同的事務可以使用不同的索引鎖定不同的行,另外,不論是使用主鍵索引、唯一索引或普通索引,InnoDB都會使用行鎖來對資料加鎖。
(4)即便在條件中使用了索引欄位,但是否使用索引來檢索資料是由MySQL通過判斷不同執行計劃的代價來決定的,如果MySQL認為全表掃描效率更高,比如對一些很小的表,它就不會使用索引,這種情況下InnoDB將使用表鎖,而不是行鎖。因此,在分析鎖衝突時,別忘了檢查SQL的執行計劃,以確認是否真正使用了索引。
官網檔案參考:( https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html)

對於在RR級別下,對資料的寫操作不僅會鎖住行還會鎖住相鄰值之間的間隙;也就是會出現 gap 鎖 和 Next-key lock。
6、三種細粒度鎖的實現
record lock-行鎖:
gap lock-間隙鎖:
Next-Key lock-臨鍵鎖:行鎖和間隙鎖共同實現的鎖;

6.1、行鎖Record lock
實現:通過索引實現,鎖住一行記錄,鎖粒度最小,併發度高。
使用條件:等值查詢;

6.2、使用間隙鎖Gap Lock
使用條件:查詢一個不存在的值,鎖定就是該值左右的區間,就是間隙鎖。
間隙鎖與間隙鎖之間是不衝突的,跟間隙鎖衝突的是: 往間隙之間插入一條資料的這個操作 。

6.3、臨鍵鎖 Next-key Lock
臨鍵鎖鎖住的是什麼?
使用條件:範圍查詢,包含等值和區間
鎖住的是下一個記錄的左開右閉的區間;
解決了RR級別下的資料幻讀;

7、小結
Mysql的行鎖和表鎖區別:
表級鎖: 鎖住整張表。 開銷小,加鎖快;不會出現死鎖;鎖粒度最大,發生鎖衝突的概率最高,併發度低;
行級鎖: 鎖住一行資料。開銷大,加鎖慢;容易出現死鎖;鎖粒度最小,發生鎖衝突的概率最低,併發度高;
行鎖的實現:
如果有索引,那麼會先掃描索引檔案,查詢到主鍵id,通過索引鎖定行記錄實現行鎖;
如果沒有索引,就會鎖住全表的資料;
行鎖的出現大大提高了資料庫的併發度,當然實現相對複雜,並且產生死鎖的概率也提升了,使用時需要注意。
————————————————