Skip to content

Instantly share code, notes, and snippets.

@s1113950
Last active January 31, 2023 20:18
Show Gist options
  • Save s1113950/13139174eb2bed18ce4d6d876465a819 to your computer and use it in GitHub Desktop.
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
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