MySQL的伪行级锁
接触mysql之前一直以为mysql的innodb引擎所支持的行级锁和oracle,postgresql是一样的,是对数据行上加锁。但其实是不一样的,理
接触mysql之前一直以为mysql的innodb引擎所支持的行级锁和Oracle,postgresql是一样的,是对数据行上加锁。但其实是不一样的,理解不一样,对mysql的锁机制就容易产生误解。innodb的行级锁实际上是基于索引项来锁定的。以下是测试机上的验证测试过程
一.数据准备
mysql> use test; Database changed mysql> show create table t_kenyon \G *************************** 1. row *************************** Table: t_kenyon Create Table: CREATE TABLE `t_kenyon` ( `id` int(11) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=utf8 1 row in set (0.00 sec) mysql> set autocommit = 0; Query OK, 0 rows affected (0.00 sec) mysql> show variables like '%autocommit%'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec) mysql> show variables like '%innodb_lock%'; +--------------------------------+-------+ | Variable_name | Value | +--------------------------------+-------+ | innodb_lock_wait_timeout | 50 | | innodb_locks_unsafe_for_binlog | OFF | +--------------------------------+-------+ 2 rows in set (0.00 sec) mysql> select @@tx_isolation; +-----------------+ | @@tx_isolation | +-----------------+ | REPEATABLE-READ | +-----------------+ 1 row in set (0.00 sec) mysql> select * from t_kenyon; +------+ | id | +------+ | 1 | | 123 | | 789 | | 345 | | 78 | | 78 | +------+ 6 rows in set (0.00 sec)以上是测试表t_kenyon,设置提交方式为手动提交.二.过程(开启两个session,分别设置autocommit=off)
1.session 1 update mysql> update t_kenyon set id = 999 where id = 1; Query OK, 1 row affected (0.04 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from t_kenyon; +------+ | id | +------+ | 999 | | 123 | | 789 | | 345 | | 78 | | 78 | +------+ 6 rows in set (0.00 sec)2.session 2 update mysql> show variables like 'autocommit'; +---------------+-------+ | Variable_name | Value | +---------------+-------+ | autocommit | OFF | +---------------+-------+ 1 row in set (0.00 sec) mysql> select * from t_kenyon; +------+ | id | +------+ | 1 | | 123 | | 789 | | 345 | | 78 | | 78 | +------+ 6 rows in set (0.00 sec) mysql> update t_kenyon set id = 88888 where id = 345;第二个session更新的值是345,但是也一直被阻塞,直到session1被rollback或者commit,如果session1未做回滚或者提交,session2中的该阻塞在超出mysql的锁时间限制时自动回滚,该参数为innodb_lock_wait_timeout,默认值50秒 现象如下 ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
加索引后的测试
3.session 1 update
三.行级锁的扩展限制
1.相同索引阻塞
mysql> select * from t_kenyon; +------+---------+ | id | name | +------+---------+ | 1 | kenyon | | 123 | francs | | 789 | lighten | | 345 | mood | | 78 | opp | | 78 | opp | | 789 | james | +------+---------+ 7 rows in set (0.00 sec) mysql> explain select * from t_kenyon where id =1 \G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t_kenyon type: ref possible_keys: ind_kenyon key: ind_kenyon key_len: 5 ref: const rows: 1 Extra: Using where 1 row in set (0.00 sec) mysql> update t_kenyon set name = 'john' where id = 789 and name = 'james'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 02.在另外的会话中同样对id=789的另一条数据进行更新 mysql> update t_kenyon set name = 'yagobu' where id = 789 and name ='lighten'; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction mysql> update t_kenyon set name = 'yagobu' where id = 789 and name ='xxxxx'; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction这时我们可以看到即使有索引,不同数据的更新也被阻塞了,哪怕没有检索到其他数据,只要用到了同一个索引键值都会被阻塞,如上述name='xxxx'中是没有的,也被阻塞了。 所以可以引申开来,只要是在一个session中>或者
3.不同事务对表的不同索引锁定不同行
a.session 1 mysql> select * from t_kenyon; +------+------------+ | id | name | +------+------------+ | 1 | kenyon | | 123 | francs | | 345 | mood | | 78 | opp | | 78 | opp | | 789 | lighten | | 789 | james | | 899 | jiangkaish | | 902 | song | | 907 | hu | | 997 | wenjiab | +------+------------+ 11 rows in set (0.00 sec) mysql> update t_kenyon set name = 'kenyon_god' where id = 789; Query OK, 2 rows affected (0.01 sec) Rows matched: 2 Changed: 2 Warnings: 02.session 2更新另一个 mysql> update t_kenyon set name = 'koko' where name = 'hu';3.在session 1中查看进程 mysql> show processlist; +----+------+-----------+------+---------+------+----------+-----------------------------------------------------+ | Id | User | Host | db | Command | Time | State | Info | +----+------+-----------+------+---------+------+----------+-----------------------------------------------------+ | 8 | root | localhost | test | Query | 0 | NULL | show processlist | | 9 | root | localhost | test | Query | 8 | Updating | update t_kenyon set name = 'koko' where name = 'hu' | | 10 | root | localhost | NULL | Sleep | 113 | | NULL | +----+------+-----------+------+---------+------+----------+-----------------------------------------------------+ 3 rows in set (0.00 sec)可以看到被锁住了。
4.对name项加索引达到目的
a.会话1 mysql> alter table t_kenyon add index ind(name); Query OK, 0 rows affected (0.33 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> update t_kenyon set name = 'kenyon_god' where id = 789; Query OK, 2 rows affected (0.02 sec) Rows matched: 2 Changed: 2 Warnings: 0b.会话2 mysql> update t_kenyon set name = 'koko' where name = 'hu'; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
至此对表的不同行数据也达到了更新的目的。
四.总结
MYSQL的innodb引擎在查询过程中如果有基于索引扫描,可以实现行级锁定,但是该行级锁有相当的限制,查询未使用索引或表中未建索引时会触发表锁,数据量大、查询效果慢的情况下该现象将被放大,严重会导致DB奔溃。

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

Go語言是一種高效、簡潔且易於學習的程式語言,因其在並發程式設計和網路程式設計方面的優勢而備受開發者青睞。在實際開發中,資料庫操作是不可或缺的一部分,本文將介紹如何使用Go語言實作資料庫的增刪改查操作。在Go語言中,我們通常會使用第三方函式庫來操作資料庫,例如常用的sql套件、gorm等。這裡以sql包為例介紹如何實作資料庫的增刪改查操作。假設我們使用的是MySQL資料庫。

蘋果公司最新發布的iOS18、iPadOS18以及macOSSequoia系統為Photos應用程式增添了一項重要功能,旨在幫助用戶輕鬆恢復因各種原因遺失或損壞的照片和影片。這項新功能在Photos應用的"工具"部分引入了一個名為"已恢復"的相冊,當用戶設備中存在未納入其照片庫的圖片或影片時,該相冊將自動顯示。 "已恢復"相簿的出現為因資料庫損壞、相機應用未正確保存至照片庫或第三方應用管理照片庫時照片和視頻丟失提供了解決方案。使用者只需簡單幾步

Hibernate多態映射可映射繼承類別到資料庫,提供以下映射類型:joined-subclass:為子類別建立單獨表,包含父類別所有欄位。 table-per-class:為子類別建立單獨資料表,僅包含子類別特有列。 union-subclass:類似joined-subclass,但父類別表聯合所有子類別列。

如何在PHP中使用MySQLi建立資料庫連線:包含MySQLi擴充(require_once)建立連線函數(functionconnect_to_db)呼叫連線函數($conn=connect_to_db())執行查詢($result=$conn->query())關閉連線( $conn->close())

PHP處理資料庫連線報錯,可以使用下列步驟:使用mysqli_connect_errno()取得錯誤代碼。使用mysqli_connect_error()取得錯誤訊息。透過擷取並記錄這些錯誤訊息,可以輕鬆識別並解決資料庫連接問題,確保應用程式的順暢運作。

HTML無法直接讀取資料庫,但可以透過JavaScript和AJAX實作。其步驟包括建立資料庫連線、發送查詢、處理回應和更新頁面。本文提供了利用JavaScript、AJAX和PHP來從MySQL資料庫讀取資料的實戰範例,展示如何在HTML頁面中動態顯示查詢結果。此範例使用XMLHttpRequest建立資料庫連接,發送查詢並處理回應,從而將資料填入頁面元素中,實現了HTML讀取資料庫的功能。

PHP是一種廣泛應用於網站開發的後端程式語言,它具有強大的資料庫操作功能,常用於與MySQL等資料庫進行互動。然而,由於中文字元編碼的複雜性,在處理資料庫中文亂碼時常常會出現問題。本文將介紹PHP處理資料庫中文亂碼的技巧與實踐,包括常見的亂碼原因、解決方法和具體的程式碼範例。常見的亂碼原因資料庫字元集設定不正確:資料庫建立時需選擇正確的字元集,如utf8或u

透過Go標準庫database/sql包,可以連接到MySQL、PostgreSQL或SQLite等遠端資料庫:建立包含資料庫連接資訊的連接字串。使用sql.Open()函數開啟資料庫連線。執行SQL查詢和插入操作等資料庫操作。使用defer關閉資料庫連線以釋放資源。
