J'ai une question plutôt fondamentale sur les transactions.
[.____] supposons une table Account
avec un montant de colonne. Maintenant, nous avons le code suivant:
BEGIN
$amount = SELECT amount FROM ACCOUNT WHERE id = 123;
$amount = $amount - 100;
UPDATE ACCOUNT SET amount = $amount WHERE id = 123;
COMMIT
Maintenant, si cet extrait se déroule simultanément par 2 transactions, T1 et T2, que se passeront-ils?
[.____] Je sais que dans MySQL par défaut, le niveau d'isolement est REPEATABLE READ
.
[.____] Alors disons que le montant initialement est de 500.
[.____] alors lorsque les 2 transactions finissent, le montant final sera-t-il 300 ou 100?
[.____] Je veux dire quand ils commencent tous les deux lire de la table que je suppose est une serrure partagée.
[.____] Quand on met à jour la table, il obtient un droit de verrou exclusif? Alors, qu'advient-il de l'autre transaction? Procédera-t-il avec le montant "View" quand il a commencé I.E. 500?
Il n'y a pas de verrou partagé implicite dans lecture répétable niveau d'isolement.
Vous devez modifier la séquence de transaction comme suit:
Vous pouvez passer à la [~ # ~] sérialisable [~ # ~ ~] niveau d'isolement et désactiver l'autocommande. De cette façon, la ligne est verrouillée en mode partagé implicitement.
Si vous voulez rester avec lecture répétable ou lu engagée , vous devrez appeler Sélectionnez ... pour mettre à jour manuellement avant de faire la mise à jour.
Vous devriez également expérimenter avec
UPDATE ACCOUNT SET amount = amount - 100 WHERE id = 123;
avec l'autocommande handicapés et SÉRIALISABLE niveau d'isolement.
Je l'ai suggéré parce que vous faites deux questions (sélectionnez et mettez à jour) pour modifier le montant. Vous pourriez simplement le faire avec une requête.
Étant donné que le verrouillage lit et non implicitement avec lecture répétable , il y a une possibilité de 500 étant utilisée deux fois.
Tu as demandé
Est-il possible de définir le niveau d'isolement à un niveau de connexion? I.e. Ne touchez pas le niveau d'isolement global?
Oui, Vous pouvez définir le niveau d'isolation dans la session :
SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL {
REPEATABLE READ
| READ COMMITTED
| READ UNCOMMITTED
| SERIALIZABLE }
Je pense que le montant sera de 400 après deux transactions commettes.
Testons. Session 1:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT amount FROM ACCOUNT WHERE id = 123;
+--------+
| amount |
+--------+
| 500 |
+--------+
1 row in set (0.00 sec)
Session n ° 2:
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT amount FROM ACCOUNT WHERE id = 123;
+--------+
| amount |
+--------+
| 500 |
+--------+
1 row in set (0.00 sec)
Session 1
mysql> UPDATE ACCOUNT SET amount = 400 WHERE id = 123;
Query OK, 0 rows affected (2.63 sec)
Rows matched: 1 Changed: 0 Warnings: 0
Session n ° 2
mysql> UPDATE ACCOUNT SET amount = 400 WHERE id = 123;
... waiting for a RW lock held by session #1
Session 1
mysql> commit;
Session n ° 2
Query OK, 0 rows affected (2.63 sec)
Rows matched: 1 Changed: 0 Warnings: 0
mysql> commit;
Query OK, 0 rows affected (0.01 sec)
Soit une session:
mysql> SELECT amount FROM ACCOUNT WHERE id = 123;
+--------+
| amount |
+--------+
| 400 |
+--------+
1 row in set (0.00 sec)