看你的需求!
mysql 的 innodb 支持多种事务隔离级别:
- READ UNCOMMITTED
- READ COMMITTED
- REPEATABLE READ
- SERIALIZABLE
默认的隔离级别是 REPEATABLE READ
pgsql 的默认的隔离级别是READ COMMITTED
;sql server 默认是READ UNCOMMITTED
; oracle 默认是Read Committed
我们使用 mysql 的默认事务隔离级别,又关闭了自动提交事务:SET AUTOCOMMIT = 0
。又恰巧,你使用 select 后不使用 commit。那你这辈子会只能读取到重复的数据。
比如下面一个表:
连接 1 ,读取 id = 1 的 row
连接 2,修改 id=1 的 row 的 name 为 pon
这个时候,连接 1 再读取 id=1 的 row,你觉得 name 是什么?是 1 还是 pon?
答案是 1 ,而不是 pon
这很可怕
那要怎么才能读取到 pon 而不是 1 呢?
- 方案一:对于连接 1,select 之后,指定 commit、roollback、begin 等等操作,来新开一个事务
- 方案二:调整事务隔离级别为
READ COMMITTED
import pymysql
import pymysql.cursors
from pymysql.connections import Connection
from loguru import logger
# Connect to the database
connection_1: Connection = pymysql.connect(host='192.168.31.245',
user='root',
password='xxxx',
port=3306,
database='seckill',
cursorclass=pymysql.cursors.DictCursor)
cursor_1 = connection_1.cursor()
connection_2: Connection = pymysql.connect(host='192.168.31.245',
user='root',
password='xxxx',
port=3306,
database='seckill',
cursorclass=pymysql.cursors.DictCursor)
cursor_2 = connection_2.cursor()
sql = """
SELECT * FROM account WHERE id=1;
""".strip()
cursor_1.execute(sql)
logger.debug(cursor_1.fetchall())
connection_1.commit()
# sql = """
# DELETE FROM account where name='jike';
# """.strip()
sql = """
UPDATE account SET name="pon" WHERE id=1;
""".strip()
cursor_2.execute(sql)
connection_2.commit()
sql = """
SELECT * FROM account WHERE id=1;
""".strip()
cursor_1.execute(sql)
logger.debug(cursor_1.fetchall())
调整事务隔离级别,有 SESSION 和 GLOBAL 两种作用域
SET {SESSION | GLOBAL} TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE};
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。