Last active
January 31, 2023 20:18
-
-
Save s1113950/13139174eb2bed18ce4d6d876465a819 to your computer and use it in GitHub Desktop.
Attempt at fixing https://bugs.mysql.com/bug.php?id=72439 with insert instead and sqlalchemy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from sqlalchemy import create_engine | |
from sqlalchemy.orm import sessionmaker | |
from multiprocessing import Process | |
from sqlalchemy.ext.declarative import declarative_base | |
from sqlalchemy import Column, Integer, String, Integer | |
from sqlalchemy import func, UniqueConstraint | |
Base = declarative_base() | |
class Models(Base): | |
__tablename__ = 'model_test' | |
__table_args__ = (UniqueConstraint('tenant_id', 'short_id', name='tenant_id_short_id_constraint'),) | |
id = Column(Integer, primary_key=True) | |
tenant_id = Column(Integer, nullable=False) | |
short_id = Column(Integer, nullable=False) | |
def setup(create = False): | |
# engine = create_engine('mysql://username:pass@something.com/db_here', | |
# echo=False) | |
engine = create_engine('mysql://username:pass@something.com/db_here') | |
if create: | |
Base.metadata.create_all(engine) | |
return sessionmaker(bind=engine, autocommit = False) | |
def insert_orm(ses, tenant_id): | |
# .with_hint(Models, "IGNORE INDEX (tenant_id_short_id_constraint)").with_for_update().scalar() | |
short_id = ses.query(func.max(Models.short_id)).filter_by(tenant_id=tenant_id)\ | |
.with_for_update() | |
if short_id is None: | |
short_id = 0 | |
# model = Models(tenant_id=tenant_id, short_id=short_id + 1) | |
# ses.add(model) | |
# ses.execute("INSERT INTO model_test (short_id, tenant_id) values ((SELECT ifnull(max(model_alias.short_id), 0) + 1 AS max_1 FROM (SELECT * FROM model_test) as model_alias WHERE model_alias.tenant_id = {} FOR UPDATE), {})".format(tenant_id, tenant_id)) | |
ses.execute("SELECT @max_1 := ifnull(max(model_test.short_id), 0) + 1 FROM model_test WHERE model_test.tenant_id = {} FOR UPDATE; INSERT INTO model_test (short_id, tenant_id) values (max_1, {})".format(tenant_id, tenant_id)) | |
def transact(ses, func, tenant_id): | |
func(ses, tenant_id) | |
ses.commit() | |
def task(tenant_id): | |
Session = setup(); | |
ses = Session() | |
for i in range(100): | |
transact(ses, insert_orm, tenant_id) | |
setup(True) | |
processes = [] | |
for m in range(15): | |
p = Process(target=task, args=(m % 5,)) | |
p.start() | |
processes.append(p) | |
for p in processes: | |
p.join() | |
# NOTE: THIS DOES NOT WORK DUE TO DEADLOCK ISSUE IN TITLE |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment