久久久精品一区ed2k-女人被男人叉到高潮的视频-中文字幕乱码一区久久麻豆樱花-俄罗斯熟妇真实视频

mysql更新怎么加行鎖 mysql中如何更新數(shù)據(jù)

MySQL - for update 行鎖 表鎖

for update 的作用是在查詢的時候為行加上排它鎖,當一個事務(wù)的操作未完成時候,其他事務(wù)可以讀取但是不能寫入或更新。

創(chuàng)新互聯(lián)公司制作網(wǎng)站網(wǎng)頁找三站合一網(wǎng)站制作公司,專注于網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計制作、做網(wǎng)站,網(wǎng)站設(shè)計,企業(yè)網(wǎng)站搭建,網(wǎng)站開發(fā),建網(wǎng)站業(yè)務(wù),680元做網(wǎng)站,已為上1000家服務(wù),創(chuàng)新互聯(lián)公司網(wǎng)站建設(shè)將一如既往的為我們的客戶提供最優(yōu)質(zhì)的網(wǎng)站建設(shè)、網(wǎng)絡(luò)營銷推廣服務(wù)!

它的典型使用場景是 高并發(fā)并且對于數(shù)據(jù)的準確性有很高要求 ,比如金錢、庫存等,一般這種操作都是很長一串并且開啟事務(wù)的,假如現(xiàn)在要對庫存進行操作,在剛開始讀的時候是1,然后馬上另外一個進程將庫存更新為0了,但事務(wù)還沒結(jié)束,會一直用1進行后續(xù)的邏輯,就會有問題,所以需要用for upate 加鎖防止出錯。

行鎖的具體實現(xiàn)算法有三種:record lock、gap lock以及next-key lock。

只在可重復(fù)讀或以上隔離級別下的特定操作才會取得 gap lock 或 next-key lock,在 Select、Update 和 Delete 時,除了基于唯一索引的查詢之外,其它索引查詢時都會獲取 gap lock 或 next-key lock,即鎖住其掃描的范圍。主鍵索引也屬于唯一索引,所以主鍵索引是不會使用 gap lock 或 next-key lock

for update 僅適用于InnoDB,并且必須開啟事務(wù),在begin與commit之間才生效。

select 語句默認不獲取任何鎖,所以是可以讀被其它事務(wù)持有排它鎖的數(shù)據(jù)的!

InnoDB 既實現(xiàn)了行鎖,也實現(xiàn)了表鎖。

當有明確指定的主鍵/索引時候,是行級鎖,否則是表級鎖

假設(shè)表 user,存在有id跟name字段,id是主鍵,有5條數(shù)據(jù)。

明確指定主鍵,并且有此記錄,行級鎖

無主鍵/索引,表級鎖

主鍵/索引不明確,表級鎖

明確指定主鍵/索引,若查無此記錄,無鎖

參考博文:

mysql的行級鎖加在哪個位置

以下五種方法可以快速定位全局鎖的位置,僅供參考。

方法1:利用 metadata_locks 視圖

此方法僅適用于 MySQL 5.7 以上版本,該版本 performance_schema 新增了 metadata_locks,如果上鎖前啟用了元數(shù)據(jù)鎖的探針(默認是未啟用的),可以比較容易的定位全局鎖會話。

方法2:利用 events_statements_history 視圖此方法適用于 MySQL 5.6 以上版本,啟用 performance_schema.eventsstatements_history(5.6 默認未啟用,5.7 默認啟用),該表會 SQL 歷史記錄執(zhí)行,如果請求太多,會自動清理早期的信息,有可能將上鎖會話的信息清理掉。

方法3:利用 gdb 工具如果上述兩種都用不了或者沒來得及啟用,可以嘗試第三種方法。利用 gdb 找到所有線程信息,查看每個線程中持有全局鎖對象,輸出對應(yīng)的會話 ID,為了便于快速定位,我寫成了腳本形式。也可以使用 gdb 交互模式,但 attach mysql 進程后 mysql 會完全 hang 住,讀請求也會受到影響,不建議使用交互模式。

方法4:show processlist

如果備份程序使用的特定用戶執(zhí)行備份,如果是 root 用戶備份,那 time 值越大的是持鎖會話的概率越大,如果業(yè)務(wù)也用 root 訪問,重點是 state 和 info 為空的,這里有個小技巧可以快速篩選,篩選后嘗試 kill 對應(yīng) ID,再觀察是否還有 wait global read lock 狀態(tài)的會話。

方法5:重啟試試!

mysql 的鎖以及間隙鎖

mysql 為并發(fā)事務(wù)同時對一條記錄進行讀寫時,提出了兩種解決方案:

1)使用 mvcc 的方法,實現(xiàn)多事務(wù)的并發(fā)讀寫,但是這種讀只是“快照讀”,一般讀的是歷史版本數(shù)據(jù),還有一種是“當前讀”,一般加鎖實現(xiàn)“當前讀”,或者 insert、update、delete 也是當前讀。

2)使用加鎖的方法,鎖分為共享鎖(讀鎖),排他鎖(寫鎖)

快照讀:就是select

當前讀:特殊的讀操作,插入/更新/刪除操作,屬于當前讀,處理的都是當前的數(shù)據(jù),需要加鎖。

mysql 在 RR 級別怎么處理幻讀的呢?一般來說,RR 級別通過 mvcc 機制,保證讀到低于后面事務(wù)的數(shù)據(jù)。但是 select for update 不會觸發(fā) mvcc,它是當前讀。如果后面事務(wù)插入數(shù)據(jù)并提交,那么在 RR 級別就會讀到插入的數(shù)據(jù)。所以,mysql 使用 行鎖 + gap 鎖(簡稱 next-key 鎖)來防止當前讀的時候插入。

Gap Lock在InnoDB的唯一作用就是防止其他事務(wù)的插入操作,以此防止幻讀的發(fā)生。

Innodb自動使用間隙鎖的條件:

Java如何實現(xiàn)對Mysql數(shù)據(jù)庫的行鎖

下面通過一個例子來說明

場景如下:

用戶賬戶有余額,當發(fā)生交易時,需要實時更新余額。這里如果發(fā)生并發(fā)問題,那么會造成用戶余額和實際交易的不一致,這對公司和客戶來說都是很危險的。

那么如何避免:

網(wǎng)上查了下,有以下兩種方法:

1、使用悲觀鎖

當需要變更余額時,通過代碼在事務(wù)中對當前需要更新的記錄設(shè)置for update行鎖,然后開始正常的查詢和更新操作

這樣,其他的事務(wù)只能等待該事務(wù)完成后方可操作

當然要特別注意,如果使用了Spring的事務(wù)注解,需要配置一下:

!-- (事務(wù)管理)transaction manager, use JtaTransactionManager for global tx --

bean id="transactionManager"

class="org.springframework.jdbc.datasource.DataSourceTransactionManager"

property name="dataSource" ref="dataSource" /

/bean

!-- 使用annotation定義事務(wù) --

tx:annotation-driven transaction-manager="transactionManager" /

在指定代碼處添加事務(wù)注解

@Transactional

@Override

public boolean increaseBalanceByLock(Long userId, BigDecimal amount)

throws ValidateException {

long time = System.currentTimeMillis();

//獲取對記錄的鎖定

UserBalance balance = userBalanceDao.getLock(userId);

LOGGER.info("[lock] start. time: {}", time);

if (null == balance) {

throw new ValidateException(

ValidateErrorCode.ERRORCODE_BALANCE_NOTEXIST,

"user balance is not exist");

}

boolean result = userBalanceDao.increaseBalanceByLock(balance, amount);

long timeEnd = System.currentTimeMillis();

LOGGER.info("[lock] end. time: {}", timeEnd);

return result;

}

MyBatis中的鎖定方式,實際測試該方法確實可以有效控制,不過在大并發(fā)量的情況下,可能會有性能問題吧

select id="getLock" resultMap="BaseResultMap" parameterType="java.lang.Long"

![CDATA[

select * from user_balance where id=#{id,jdbcType=BIGINT} for update;

]]

/select

2、使用樂觀鎖

這個方法也同樣可以解決場景中描述的問題(我認為比較適合并不頻繁的操作):

設(shè)計表的時候增加一個version(版本控制字段),每次需要更新余額的時候,先獲取對象,update的時候根據(jù)version和id為條件去更新,如果更新回來的數(shù)量為0,說明version已經(jīng)變更

需要重復(fù)一次更新操作,如下:sql腳本

update user_balance set Balance = #{balance,jdbcType=DECIMAL},Version = Version+1 where Id = #{id,jdbcType=BIGINT} and Version = #{version,jdbcType=BIGINT}

這是一種不使用數(shù)據(jù)庫鎖的方法,解決方式也很巧妙。當然,在大量并發(fā)的情況下,一次扣款需要重復(fù)多次的操作才能成功,還是有不足之處的。不知道還有沒有更好的方法。

當前題目:mysql更新怎么加行鎖 mysql中如何更新數(shù)據(jù)
當前網(wǎng)址:http://www.sd-ha.com/article28/dohjejp.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站制作、網(wǎng)站收錄、自適應(yīng)網(wǎng)站、品牌網(wǎng)站建設(shè)、網(wǎng)站內(nèi)鏈、企業(yè)網(wǎng)站制作

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)頁設(shè)計公司