ロック機構
共有ロックと排他ロック
共有ロック (読み取りロック): 他のトランザクションは読み取りはできますが、書き込みはできません。
排他的ロック (書き込みロック): 他のトランザクションは読み書きできません。
MySQL には、ページ レベル、テーブル レベル、行レベルの 3 つのロック レベルがあります。
- ページ レベルの代表的なエンジンは BDB です。
- 行レベルの代表的なエンジンは INNODB です。
- テーブルレベルの代表的なエンジンとしては、MyISAM、MEMORY、そして一昔前のISAMなどが挙げられます。
- BDB ストレージ エンジンはページ レベルのロックを使用しますが、テーブル レベルのロックもサポートします
- InnoDB ストレージ エンジンは行レベルのロック (行レベルのロック) とテーブル レベルのロックの両方をサポートします。 -レベルのロックですが、デフォルトでは行レベルのロックが使用されます。
- MyISAM および MEMORY ストレージ エンジンはテーブル レベルのロックを使用します
関連する無料学習の推奨事項: php プログラミング (ビデオ)
MyISAM テーブル レベル ロック モード:
- テーブル共有読み取りロック (テーブル読み取りロック): いいえ同じテーブルに対する他のユーザーの読み取りリクエストはブロックされますが、同じテーブルに対する他のユーザーの書き込みリクエストはブロックされます。
- テーブル排他的書き込みロック (テーブル書き込みロック): 他のユーザーの読み取りおよび書き込み操作をブロックします。同じテーブル上;
MyISAM テーブルのロック方法:
- LOCK TABLE コマンドを使用して、MyISAM テーブルを明示的にロックします
- LOCK TABLES real_table (READ |WRITE), insert_table (READ|WRITE); //Lock
- UNLOCK TABLES; //Unlock
例:
たとえば、 is account(id,name,cash), hero (number, name, country) これら 2 つのテーブル
- ロック テーブル アカウントの読み取り; アカウントを読み取り専用ロックとして追加します
現在のプロセス クエリ: select * from hero; will レポート テーブル 'hero' が LOCK TABLES でロックされていませんでした。
現在のプロセスは他のテーブルを変更します: update hero set name="ss" wherenumber=1; will report Table 'hero' was not locked with LOCK TABLES
現在のプロセスはテーブルを変更します: update account set name= "ssss" where id=1; テーブル 'account' が READ ロックでロックされており、更新できないことが報告されます
別の mysql プロセスが入ってきた場合、他のテーブルやアカウントをクエリすることはできますが、変更することはできませんロックが実行される
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2021/4/29 0029 * Time: 11:20 */$link = new mysqli('127.0.0.1', 'root', '123', 'db_school'); // 连接数据库if(mysqli_connect_errno()){ // 检查连接错误 printf("连接失败:%s<br>", mysqli_connect_error()); exit();}//(s1)$table = "account";$type = "read";$sql1 = "LOCK TABLES $table $type";$link->query($sql1);//处理逻辑//$sql1 = "select * from $table;"; //(s1)true//$sql1 = "select * from hero;"; //false//$sql1 = "update hero set name='ss' where number=1; "; //false$sql1 = "update account set name='ssss' where id=1;"; //false$result = $link->query($sql1);var_dump($result);sleep(20); //测试 //假设还没释放锁,开启cmd进mysql(s2)可以查询,但不能执行更改和删除操作,会等待这边释放锁$link->query("unlock tables"); //取消全部的锁//解锁后正常操作//$result = $link -> query($sql1);//var_dump($result);$link->close();
クエリテーブルレベルのロック競合
'Table%' のようなステータスを表示;
- Table_locks_immediate は、テーブル レベルのロックをすぐに取得できる回数を指します。
- Table_locks_waited は、テーブル レベルのロックをすぐに取得できる回数を指します。レベル ロックはすぐには取得できないため、待つ必要があります。
通常の SELECT ステートメントの場合、InnoDB はロックを追加しません。 ##ロックはトランザクション実行中のみ使用できます ロックはトランザクション実行中のみ使用できます。コミットまたはロールバックが実行された場合にのみ解放され、すべてのロックが同時に解放されます。
共有ロック(S): SELECT * FROM table_name WHERE ... 共有モードでロックします。他のセッションは引き続きレコードをクエリし、共有モードの共有ロックをレコードに追加できます。ただし、現在のトランザクションでレコードを更新する必要がある場合は、デッドロックが発生する可能性があります。誰でも読み取ることができますが、変更することはできません。排他的共有ロックの 1 つがロックされている場合にのみ変更できます;
2.1PHP 操作- 排他的ロック (X): SELECT * FROM table_name WHERE ... FOR UPDATE。他のセッションはレコードをクエリできますが、レコードに共有ロックや排他ロックを追加することはできず、ロックの取得を待ちます。変更したいのですが、変更できず、読み取ることもできません
- #select … 共有モードでロック //共有ロック
#select … 更新用 //排他ロック
##MySQL 8.0 の場合
共有ロック (S): SELECT * FROM table_name WHERE … FOR SHARE- 排他ロック (X): SELECT * FROM table_name WHERE … FOR UPDATE[NOWAIT|SKIP LOCKED] ]
–NOWAIT: Discovery ロックを待った後、すぐにエラーが返されるため、ロックのタイムアウトを待ってエラーを報告する必要はありません。- –SKIP LOCKED: ロックされた行をスキップし、他の行を直接更新しますが、更新結果が期待を満たさないかどうかに注意してください。
<?php/** * Created by PhpStorm. * User: Administrator * Date: 2021/4/29 0029 * Time: 10:06 */$link = new mysqli('127.0.0.1', 'root', '123', 'db_school'); // 连接数据库if(mysqli_connect_errno()){ // 检查连接错误 printf("连接失败:%s<br>", mysqli_connect_error()); exit();}//案例1$id = 1; //明确指定主键,并且有此数据,row lock (行锁)//$id = -1; //明确指定主键,若查无此数据,无lock (无锁)$link->autocommit(0); // 开始事务(s1)//FOR UPDATE仅适用于InnoDB,且必须在交易区块(BEGIN/COMMIT)中才能生效。$sql = "select * from account where id=$id for update";$link->query($sql);/*** * 此时其他mysql进程可以查询该记录,但是不能对该记录加共享锁或排他锁,而是等待获得锁。 *///(s1)可以进行更改,和查询等操作//$sql1 = "update account set name='aaa' where id=$id;"; //进行更改//$sql1 = "select * from account where id=$id;"; //进行查询$sql1 = "delete from account where id=$id;"; //进行删除$result = $link -> query($sql1);var_dump($result);sleep(20); //测试 //假设还在事务处理中,开启cmd进mysql(s2)执行更改和删除操作,会等待这边释放锁$link->commit();$link->close();
show OPEN TABLES where In_use > 0;SHOW PROCESSLIST どのスレッドを表示走っている。
以上がPHP の mysql ロック メカニズムの簡単な操作の簡単な分析の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。