innodb存儲引擎不須要鎖升級,由於一個鎖和多個鎖的開銷是相同的。mysql
鎖是數據庫系統區別於文件系統的一個關鍵特性。鎖機制用於管理對共享資源的併發訪問。Innodb引擎中使用鎖的地方有多個:在行級別上對錶數據上鎖;操做緩衝池中的LRU列表,刪除,添加,移動LRU列表中的元素。sql
鎖信息的查看命令:數據庫
innodb實現了兩種標準的行級鎖:架構
鎖兼容:若是一個事務T1已經得到了r行的共享鎖,那麼另外的事務T2能夠當即得到行r的共享鎖,由於讀取並無改變行r的數據。併發
鎖不兼容:若是T3想得到r行的x鎖,則必須等T1,T2釋放行r上的S鎖spa
X | S | |
X | 不兼容 | 不兼容 |
S | 不兼容 | 兼容 |
innodb支持兩個鐘意向鎖(在innodb中即爲表鎖):orm
查看innodb隔離級別:blog
mysql> SELECT @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | REPEATABLE-READ | +-----------------------+ 1 row in set (0.00 sec)
實驗過程:事務
建表test:資源
mysql> CREATE TABLE `test` ( -> `id` bigint(20) NOT NULL, -> `name` varchar(20) NOT NULL DEFAULT "name", -> PRIMARY KEY (id), -> KEY `index_name` (`name`) -> ) ENGINE=InnoDB DEFAULT CHARSET=utf8; Query OK, 0 rows affected (0.99 sec)
填充數據:
mysql> insert into test (id) values(1),(2),(3),(9); Query OK, 4 rows affected (0.08 sec) Records: 4 Duplicates: 0 Warnings: 0 mysql> select * from test; +----+------+ | id | name | +----+------+ | 1 | name | | 2 | name | | 3 | name | | 9 | name | +----+------+ 4 rows in set (0.00 sec)
實驗數據:
說明:事務一,事務二都有數據,順序是先執行事務一,再執行事務二。
事務一 | 事務二 | innodb_trx | innodb_locks | innodb_lock_waits |
mysql> begin; select * from test where id=1 for update; Query OK, 0 rows affected (0.00 sec) +----+------+ | id | name | +----+------+ | 1 | name | +----+------+ 1 row in set (0.00 sec)
|
mysql> select * from information_schema.INNODB_TRX\G *************************** 1. row *************************** trx_id: 1074396261 trx_state: RUNNING trx_started: 2017-04-26 15:18:25 trx_requested_lock_id: NULL trx_wait_started: NULL trx_weight: 2 trx_mysql_thread_id: 8950735 trx_query: NULL trx_operation_state: NULL trx_tables_in_use: 0 trx_tables_locked: 0 trx_lock_structs: 2 trx_lock_memory_bytes: 376 trx_rows_locked: 1 trx_rows_modified: 0 trx_concurrency_tickets: 0 trx_isolation_level: REPEATABLE READ trx_unique_checks: 1 trx_foreign_key_checks: 1 trx_last_foreign_key_error: NULL trx_adaptive_hash_latched: 0 trx_adaptive_hash_timeout: 10000 trx_is_read_only: 0 trx_autocommit_non_locking: 0 1 row in set (0.00 sec)
|
mysql> select * from information_schema.INNODB_LOCKS\G Empty set (0.00 sec)
|
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS\G Empty set (0.00 sec)
|
|
mysql> begin;select * from test where id=1 lock in share mode; Query OK, 0 rows affected (0.00 sec)
|
mysql> select * from information_schema.INNODB_TRX\G *************************** 1. row *************************** trx_id: 1074397998 trx_state: LOCK WAIT trx_started: 2017-04-26 15:21:02 trx_requested_lock_id: 1074397998:5594:3:2 trx_wait_started: 2017-04-26 15:21:02 trx_weight: 2 trx_mysql_thread_id: 8959888 trx_query: select * from test where id=1 lock in share mode trx_operation_state: starting index read trx_tables_in_use: 1 trx_tables_locked: 1 trx_lock_structs: 2 trx_lock_memory_bytes: 376 trx_rows_locked: 1 trx_rows_modified: 0 trx_concurrency_tickets: 0 trx_isolation_level: REPEATABLE READ trx_unique_checks: 1 trx_foreign_key_checks: 1 trx_last_foreign_key_error: NULL trx_adaptive_hash_latched: 0 trx_adaptive_hash_timeout: 10000 trx_is_read_only: 0 trx_autocommit_non_locking: 0 *************************** 2. row *************************** trx_id: 1074396261 trx_state: RUNNING trx_started: 2017-04-26 15:18:25 trx_requested_lock_id: NULL trx_wait_started: NULL trx_weight: 2 trx_mysql_thread_id: 8950735 trx_query: NULL trx_operation_state: NULL trx_tables_in_use: 0 trx_tables_locked: 0 trx_lock_structs: 2 trx_lock_memory_bytes: 376 trx_rows_locked: 1 trx_rows_modified: 0 trx_concurrency_tickets: 0 trx_isolation_level: REPEATABLE READ trx_unique_checks: 1 trx_foreign_key_checks: 1 trx_last_foreign_key_error: NULL trx_adaptive_hash_latched: 0 trx_adaptive_hash_timeout: 10000 trx_is_read_only: 0 trx_autocommit_non_locking: 0 2 rows in set (0.00 sec)
|
mysql> select * from information_schema.INNODB_LOCKS\G *************************** 1. row *************************** lock_id: 1074397998:5594:3:2 lock_trx_id: 1074397998 lock_mode: S lock_type: RECORD lock_table: `ztest`.`test` lock_index: PRIMARY lock_space: 5594 lock_page: 3 lock_rec: 2 lock_data: 1 *************************** 2. row *************************** lock_id: 1074396261:5594:3:2 lock_trx_id: 1074396261 lock_mode: X lock_type: RECORD lock_table: `ztest`.`test` lock_index: PRIMARY lock_space: 5594 lock_page: 3 lock_rec: 2 lock_data: 1 2 rows in set (0.00 sec)
|
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS\G *************************** 1. row *************************** requesting_trx_id: 1074397998 requested_lock_id: 1074397998:5594:3:2 blocking_trx_id: 1074396261 blocking_lock_id: 1074396261:5594:3:2 1 row in set (0.00 sec)
|
|
mysql> update test set name="name1" where id=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from test; +----+-------+ | id | name | +----+-------+ | 2 | name | | 3 | name | | 9 | name | | 1 | name1 | +----+-------+ 4 rows in set (0.00 sec)
|
mysql> select * from test; +----+------+ | id | name | +----+------+ | 1 | name | | 2 | name | | 3 | name | | 9 | name | +----+------+ 4 rows in set (0.00 sec) 該查詢下,id爲1的行,並無修改name,由於事務一的修改並無提交。 |
|||
mysql> commit -> ; Query OK, 0 rows affected (0.08 sec) mysql> select * from test; +----+-------+ | id | name | +----+-------+ | 2 | name | | 3 | name | | 9 | name | | 1 | name1 | +----+-------+ 4 rows in set (0.00 sec)
|
mysql> select * from test; +----+------+ | id | name | +----+------+ | 1 | name | | 2 | name | | 3 | name | | 9 | name | +----+------+ 4 rows in set (0.00 sec) 事務一,已經提交,該查詢下,id爲1的行,name沒有發生變化,代表在RR隔離級別下的,可重複讀:同一個事務的,同一個select讀出的數據徹底一致。 |
|||
mysql> commit; Query OK, 0 rows affected (0.00 sec) mysql> select * from test; +----+-------+ | id | name | +----+-------+ | 2 | name | | 3 | name | | 9 | name | | 1 | name1 | +----+-------+ 4 rows in set (0.00 sec) 兩個事務都結束了。 |
||||
實驗二 | ||||
事務一 | 事務二 | innodb_trx | innodb_locks | innodb_lock_waits |
mysql> begin;select * from test where id>0 and id<5 for update; Query OK, 0 rows affected (0.00 sec) +----+-------+ | id | name | +----+-------+ | 2 | name | | 3 | name | | 1 | name1 | +----+-------+ 3 rows in set (0.00 sec)
|
mysql> begin;update test set name="nihao" where id=1; Query OK, 0 rows affected (0.00 sec) select * from test; 事務二的兩個操做都被阻塞 |
mysql> select * from information_schema.INNODB_LOCKS\G *************************** 1. row *************************** lock_id: 1074413840:5594:3:6 lock_trx_id: 1074413840 lock_mode: X lock_type: RECORD lock_table: `ztest`.`test` lock_index: PRIMARY lock_space: 5594 lock_page: 3 lock_rec: 6 lock_data: 1 *************************** 2. row *************************** lock_id: 1074413574:5594:3:6 lock_trx_id: 1074413574 lock_mode: X lock_type: RECORD lock_table: `ztest`.`test` lock_index: PRIMARY lock_space: 5594 lock_page: 3 lock_rec: 6 lock_data: 1 2 rows in set (0.00 sec)
|
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS\G *************************** 1. row *************************** requesting_trx_id: 1074413840 requested_lock_id: 1074413840:5594:3:6 blocking_trx_id: 1074413574 blocking_lock_id: 1074413574:5594:3:6 1 row in set (0.00 sec)
|
|
mysql> update test set name="fjsld" where id=1; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from test; +----+-------+ | id | name | +----+-------+ | 1 | fjsld | | 2 | name | | 3 | name | | 9 | name | +----+-------+ 4 rows in set (0.00 sec)
|
||||
mysql> commit; Query OK, 0 rows affected (0.02 sec)
|
mysql> update test set name="nihao" where id=1; Query OK, 1 row affected (1 min 45.44 sec) Rows matched: 1 Changed: 1 Warnings: 0
事務一提交,事務二更新成功 事務一優先獲取了X鎖,此後,事務二想要獲取X鎖,須要等候 |
常見概念:
mysql> show global variables like "%timeout%"; +-----------------------------+----------+ | Variable_name | Value | +-----------------------------+----------+ | connect_timeout | 10 | | delayed_insert_timeout | 300 | | innodb_flush_log_at_timeout | 1 | | innodb_lock_wait_timeout | 120 | | innodb_rollback_on_timeout | OFF | | interactive_timeout | 28800 | | lock_wait_timeout | 31536000 | | net_read_timeout | 30 | | net_write_timeout | 60 | | slave_net_timeout | 3600 | | wait_timeout | 28800 | +-----------------------------+----------+ 11 rows in set (0.00 sec) mysql> set innodb_lock_wait_timeout=3600; Query OK, 0 rows affected (0.00 sec)